import { NativeModules, NativeEventEmitter, EmitterSubscription } from 'react-native';

const TencentCloudPush = NativeModules.TencentCloudPush ? NativeModules.TencentCloudPush : {};

interface ListenerConfig {
  nativeListener: EmitterSubscription | undefined;
  listeners: Array<(data: any) => void>;
}

const LOG_PREFIX = 'Push js |';
export default class Push {
  static EVENT = {
    MESSAGE_RECEIVED: 'message_received',
    MESSAGE_REVOKED: 'message_revoked',
    NOTIFICATION_CLICKED: 'notification_clicked',
  };
  static EventEmitter: NativeEventEmitter = new NativeEventEmitter(NativeModules.TencentCloudPush);
  static ListenerMap: Map<String, ListenerConfig> = new Map();
  private constructor() {}
  static registerPush(SDKApppID: number, appKey: string, onSuccess: (data: string) => void, onError?: (errCode: number, errMsg: string) => void): void {
    console.log(LOG_PREFIX, 'registerPush', SDKApppID, appKey);
    if (typeof onError === 'function') {
      TencentCloudPush.registerPushWithOnError(SDKApppID, appKey, onSuccess, onError);
    } else {
      TencentCloudPush.registerPush(SDKApppID, appKey, onSuccess);
    }
  }

  static unRegisterPush(onSuccess: () => void, onError?: (errCode: number, errMsg: string) => void) {
    console.log(LOG_PREFIX, 'unRegisterPush');
    if (typeof onError === 'function') {
      TencentCloudPush.unRegisterPushWithOnError(onSuccess, onError);
    } else {
      TencentCloudPush.unRegisterPush(onSuccess);
    }
  }

  static getRegistrationID(onSuccess: (registrationID: string) => void): void {
    console.log(LOG_PREFIX, 'getRegistrationID');
    TencentCloudPush.getRegistrationID(onSuccess);
  }

  static setRegistrationID(registrationID: string,  onSuccess: () => void): void {
    console.log(LOG_PREFIX, 'setRegistrationID', registrationID);
    TencentCloudPush.setRegistrationID(registrationID, onSuccess);
  }

  static getNotificationExtInfo(onSuccess: (extInfo: string) => void): void {
    console.log(LOG_PREFIX, 'getNotificationExtInfo');
    TencentCloudPush.getNotificationExtInfo(onSuccess);
  }

  static addPushListener(eventName: string, listener: (data: any) => void): void {
    console.log(LOG_PREFIX, 'addPushListener ', eventName);
    const listenerConfig: ListenerConfig = Push.ListenerMap.get(eventName) || {
      listeners: [],
      nativeListener: undefined,
    };
    const oldListeners: Array<(data: any) => void> = listenerConfig.listeners;
    const newListeners: Array<(data: any) => void> = [listener];
    listenerConfig.listeners = [...oldListeners, ...newListeners];
    if (!listenerConfig.nativeListener) {
      listenerConfig.nativeListener = Push.EventEmitter.addListener(eventName, event => {
        let { data } = event;
        if(eventName === Push.EVENT.MESSAGE_RECEIVED) {
          try {
            data = JSON.parse(data);
          } catch (error) {
            console.log(LOG_PREFIX, `${eventName} JSON.parse error `, error);
          }
        }
        Push.ListenerMap.get(eventName)?.listeners.forEach(item => {
          if (typeof item === 'function') {
            item(data);
          }
        });
      });
    }
    Push.ListenerMap.set(eventName, listenerConfig);
  }

  static removePushListener(eventName: string, listener?: (data: any) => void): void {
    console.log(LOG_PREFIX, 'removePushListener ', eventName);
    const listenerConfig: ListenerConfig = Push.ListenerMap.get(eventName) || {
      listeners: [],
      nativeListener: undefined,
    };

    if (listener) {
      listenerConfig.listeners = listenerConfig.listeners.filter((item) => {
        return item !== listener;
      });
      Push.ListenerMap.set(eventName, listenerConfig);
    } else {
      listenerConfig.listeners = [];
    }

    if (listenerConfig.listeners.length === 0) {
      listenerConfig.nativeListener?.remove();
      Push.ListenerMap.delete(eventName);
    }
  }

  static disablePostNotificationInForeground(disable: boolean): void {
    console.log(LOG_PREFIX, 'disablePostNotificationInForeground ', disable);
    TencentCloudPush.disablePostNotificationInForeground(disable);
  }

  static createNotificationChannel(options: Record<string, any>, onSuccess: (extInfo: string) => void): void {
    const channelInfo: string = JSON.stringify(options);
    console.log(LOG_PREFIX, 'createNotificationChannel ', channelInfo);
    TencentCloudPush.createNotificationChannel(channelInfo, onSuccess);
  }
}
