import { AccessToken2, ServiceRtc, ServiceRtm } from './AccessToken2';

export enum Role {
  /**
   * 推荐使用。如果您的场景不需要对联合主播进行身份验证，
   * 请使用此角色进行语音/视频通话或直播。
   */
  PUBLISHER = 1,

  /**
   * 仅当您的场景需要对联合主播进行身份验证时才使用此角色。
   * 为了使此角色生效，请联系我们的支持团队为您启用联合主播身份验证。
   * 否则，Role_Subscriber 仍然具有与 Role_Publisher 相同的权限。
   */
  SUBSCRIBER = 2,
}

export class RtcTokenBuilder {
  /**
   * 使用 uid 构建 RTC Token
   * @param appId - 声网颁发给您的 App ID
   * @param appCertificate - 您在声网控制台注册的应用程序证书
   * @param channelName - 字符串格式的 AgoraRTC 会话的唯一频道名称
   * @param uid - 用户 ID。范围从 1 到 (2^32-1) 的 32 位无符号整数
   * @param role - 用户角色
   * @param tokenExpire - 从现在开始经过的秒数表示
   * @param privilegeExpire - 从现在开始经过的秒数表示
   * @returns RTC Token
   */
  public static buildTokenWithUid(
    appId: string,
    appCertificate: string,
    channelName: string,
    uid: number | string,
    role: Role,
    tokenExpire: number,
    privilegeExpire = 0
  ): string {
    return this.buildTokenWithUserAccount(appId, appCertificate, channelName, uid, role, tokenExpire, privilegeExpire);
  }

  /**
   * 使用账户构建 RTC Token
   * @param appId - 声网颁发给您的 App ID
   * @param appCertificate - 您在声网控制台注册的应用程序证书
   * @param channelName - 字符串格式的 AgoraRTC 会话的唯一频道名称
   * @param account - 用户账户
   * @param role - 用户角色
   * @param tokenExpire - 从现在开始经过的秒数表示
   * @param privilegeExpire - 从现在开始经过的秒数表示
   * @returns RTC Token
   */
  public static buildTokenWithUserAccount(
    appId: string,
    appCertificate: string,
    channelName: string,
    account: number | string,
    role: Role,
    tokenExpire: number,
    privilegeExpire = 0
  ): string {
    const token = new AccessToken2(appId, appCertificate, 0, tokenExpire);

    const serviceRtc = new ServiceRtc(channelName, account);
    serviceRtc.add_privilege(ServiceRtc.kPrivilegeJoinChannel, privilegeExpire);
    if (role === Role.PUBLISHER) {
      serviceRtc.add_privilege(ServiceRtc.kPrivilegePublishAudioStream, privilegeExpire);
      serviceRtc.add_privilege(ServiceRtc.kPrivilegePublishVideoStream, privilegeExpire);
      serviceRtc.add_privilege(ServiceRtc.kPrivilegePublishDataStream, privilegeExpire);
    }
    token.add_service(serviceRtc);

    return token.build();
  }

  /**
   * Generates an RTC token with the specified privilege.
   * @param appId - The App ID of your Agora project.
   * @param appCertificate - The App Certificate of your Agora project.
   * @param channelName - The unique channel name for the Agora RTC session in string format.
   * @param uid - The user ID.
   * @param tokenExpire - represented by the number of seconds elapsed since now.
   * @param joinChannelPrivilegeExpire - represented by the number of seconds elapsed since now.
   * @param pubAudioPrivilegeExpire - represented by the number of seconds elapsed since now.
   * @param pubVideoPrivilegeExpire - represented by the number of seconds elapsed since now.
   * @param pubDataStreamPrivilegeExpire - represented by the number of seconds elapsed since now.
   * @returns The RTC Token
   */
  public static buildTokenWithUidAndPrivilege(
    appId: string,
    appCertificate: string,
    channelName: string,
    uid: number | string,
    tokenExpire: number,
    joinChannelPrivilegeExpire: number,
    pubAudioPrivilegeExpire: number,
    pubVideoPrivilegeExpire: number,
    pubDataStreamPrivilegeExpire: number
  ): string {
    return this.BuildTokenWithUserAccountAndPrivilege(
      appId,
      appCertificate,
      channelName,
      uid,
      tokenExpire,
      joinChannelPrivilegeExpire,
      pubAudioPrivilegeExpire,
      pubVideoPrivilegeExpire,
      pubDataStreamPrivilegeExpire
    );
  }

  /**
   * Generates an RTC token with the specified privilege.
   * @param appId - The App ID of your Agora project.
   * @param appCertificate - The App Certificate of your Agora project.
   * @param channelName - The unique channel name for the Agora RTC session in string format.
   * @param userAccount - The user account.
   * @param tokenExpire - represented by the number of seconds elapsed since now.
   * @param joinChannelPrivilegeExpire - represented by the number of seconds elapsed since now.
   * @param pubAudioPrivilegeExpire - represented by the number of seconds elapsed since now.
   * @param pubVideoPrivilegeExpire - represented by the number of seconds elapsed since now.
   * @param pubDataStreamPrivilegeExpire - represented by the number of seconds elapsed since now.
   * @returns The RTC Token.
   */
  public static BuildTokenWithUserAccountAndPrivilege(
    appId: string,
    appCertificate: string,
    channelName: string,
    account: number | string,
    tokenExpire: number,
    joinChannelPrivilegeExpire: number,
    pubAudioPrivilegeExpire: number,
    pubVideoPrivilegeExpire: number,
    pubDataStreamPrivilegeExpire: number
  ): string {
    const token = new AccessToken2(appId, appCertificate, 0, tokenExpire);

    const serviceRtc = new ServiceRtc(channelName, account);
    serviceRtc.add_privilege(ServiceRtc.kPrivilegeJoinChannel, joinChannelPrivilegeExpire);
    serviceRtc.add_privilege(ServiceRtc.kPrivilegePublishAudioStream, pubAudioPrivilegeExpire);
    serviceRtc.add_privilege(ServiceRtc.kPrivilegePublishVideoStream, pubVideoPrivilegeExpire);
    serviceRtc.add_privilege(ServiceRtc.kPrivilegePublishDataStream, pubDataStreamPrivilegeExpire);
    token.add_service(serviceRtc);

    return token.build();
  }

  /**
   * Build an RTC and RTM token with account.
   * @param appId - The App ID issued to you by Agora.
   * @param appCertificate - Certificate of the application that you registered in the Agora Dashboard.
   * @param channelName - The unique channel name for the AgoraRTC session in the string format.
   * @param account - The user account.
   * @param role - See #userRole.
   * @param tokenExpire - represented by the number of seconds elapsed since now.
   * @param privilegeExpire - represented by the number of seconds elapsed since now.
   * @returns The RTC and RTM Token.
   */
  public static buildTokenWithRtm(
    appId: string,
    appCertificate: string,
    channelName: string,
    account: number | string,
    role: Role,
    tokenExpire: number,
    privilegeExpire = 0
  ): string {
    const token = new AccessToken2(appId, appCertificate, 0, tokenExpire);

    const serviceRtc = new ServiceRtc(channelName, account);
    serviceRtc.add_privilege(ServiceRtc.kPrivilegeJoinChannel, privilegeExpire);
    if (role === Role.PUBLISHER) {
      serviceRtc.add_privilege(ServiceRtc.kPrivilegePublishAudioStream, privilegeExpire);
      serviceRtc.add_privilege(ServiceRtc.kPrivilegePublishVideoStream, privilegeExpire);
      serviceRtc.add_privilege(ServiceRtc.kPrivilegePublishDataStream, privilegeExpire);
    }
    token.add_service(serviceRtc);

    const serviceRtm = new ServiceRtm(String(account));
    serviceRtm.add_privilege(ServiceRtm.kPrivilegeLogin, tokenExpire);
    token.add_service(serviceRtm);

    return token.build();
  }

  /**
   * Build an RTC and RTM token with account.
   * @param appId - The App ID issued to you by Agora.
   * @param appCertificate - Certificate of the application that you registered in the Agora Dashboard.
   * @param channelName - The unique channel name for the AgoraRTC session in the string format.
   * @param rtcAccount - The RTC user's account, max length is 255 Bytes.
   * @param rtcRole - See #userRole.
   * @param rtcTokenExpire - represented by the number of seconds elapsed since now.
   * @param joinChannelPrivilegeExpire - represented by the number of seconds elapsed since now.
   * @param pubAudioPrivilegeExpire - represented by the number of seconds elapsed since now.
   * @param pubVideoPrivilegeExpire - represented by the number of seconds elapsed since now.
   * @param pubDataStreamPrivilegeExpire - represented by the number of seconds elapsed since now.
   * @param rtmUserId - The RTM user's account, max length is 255 Bytes.
   * @param rtmTokenExpire - represented by the number of seconds elapsed since now.
   * @returns The RTC and RTM Token.
   */
  public static buildTokenWithRtm2(
    appId: string,
    appCertificate: string,
    channelName: string,
    rtcAccount: number | string,
    rtcRole: Role,
    rtcTokenExpire: number,
    joinChannelPrivilegeExpire: number,
    pubAudioPrivilegeExpire: number,
    pubVideoPrivilegeExpire: number,
    pubDataStreamPrivilegeExpire: number,
    rtmUserId: string,
    rtmTokenExpire: number
  ): string {
    const token = new AccessToken2(appId, appCertificate, 0, rtcTokenExpire);

    const serviceRtc = new ServiceRtc(channelName, rtcAccount);
    serviceRtc.add_privilege(ServiceRtc.kPrivilegeJoinChannel, joinChannelPrivilegeExpire);
    if (rtcRole === Role.PUBLISHER) {
      serviceRtc.add_privilege(ServiceRtc.kPrivilegePublishAudioStream, pubAudioPrivilegeExpire);
      serviceRtc.add_privilege(ServiceRtc.kPrivilegePublishVideoStream, pubVideoPrivilegeExpire);
      serviceRtc.add_privilege(ServiceRtc.kPrivilegePublishDataStream, pubDataStreamPrivilegeExpire);
    }
    token.add_service(serviceRtc);

    const serviceRtm = new ServiceRtm(rtmUserId);
    serviceRtm.add_privilege(ServiceRtm.kPrivilegeLogin, rtmTokenExpire);
    token.add_service(serviceRtm);

    return token.build();
  }
}
