import type { TimInstanceType, TimType, EventCallback } from '../types';


const getEventList = (TIM: TimType) => ([
  TIM.EVENT.SDK_READY,
  TIM.EVENT.SDK_NOT_READY,

  TIM.EVENT.TOTAL_UNREAD_MESSAGE_COUNT_UPDATED,

  TIM.EVENT.MESSAGE_RECEIVED,
  TIM.EVENT.MESSAGE_MODIFIED,
  TIM.EVENT.MESSAGE_REVOKED,
  TIM.EVENT.MESSAGE_READ_BY_PEER,
  TIM.EVENT.MESSAGE_READ_RECEIPT_RECEIVED,

  TIM.EVENT.CONVERSATION_LIST_UPDATED,

  TIM.EVENT.GROUP_LIST_UPDATED,
  TIM.EVENT.GROUP_ATTRIBUTES_UPDATED,

  TIM.EVENT.TOPIC_CREATED,
  TIM.EVENT.TOPIC_UPDATED,
  TIM.EVENT.TOPIC_DELETED,

  TIM.EVENT.PROFILE_UPDATED,
  TIM.EVENT.BLACKLIST_UPDATED,

  TIM.EVENT.FRIEND_LIST_UPDATED,
  TIM.EVENT.FRIEND_GROUP_LIST_UPDATED,
  TIM.EVENT.FRIEND_APPLICATION_LIST_UPDATED,

  TIM.EVENT.ERROR,
  TIM.EVENT.NET_STATE_CHANGE,
  TIM.EVENT.KICKED_OUT,
]);

function onReady(event: string, tim: TimInstanceType) {
  tim.updateReadyStatus?.(true);
}

function onNotReady(event: string, tim: TimInstanceType) {
  tim.updateReadyStatus?.(false);
}

function onKickOut(event: string, tim: TimInstanceType) {
  tim.updateOnlineStatus?.(false);
}


// const eventListenerMap = {
//   [TIM.EVENT.SDK_READY]: [onReady],
//   [TIM.EVENT.SDK_NOT_READY]: [onNotReady],
//   [TIM.EVENT.KICKED_OUT]: [onKickOut],
// };

const localEventCallbackMap: Record<string, Function[]> = {};

const getEventListenerMap = (TIM: TimType) => {
  localEventCallbackMap[TIM.EVENT.SDK_READY] = [
    onReady,
    ...(localEventCallbackMap[TIM.EVENT.SDK_READY] || []),
  ];

  localEventCallbackMap[TIM.EVENT.SDK_NOT_READY] = [
    onNotReady,
    ...(localEventCallbackMap[TIM.EVENT.SDK_NOT_READY] || []),
  ];

  localEventCallbackMap[TIM.EVENT.KICKED_OUT] = [
    onKickOut,
    ...(localEventCallbackMap[TIM.EVENT.KICKED_OUT] || []),
  ];

  return localEventCallbackMap;
};


function executeCallbacks({
  type,
  event,
  tim,
  TIM,
}: {
  type: string;
  event: string;
  tim: TimInstanceType;
  TIM: TimType;
}) {
  const eventListenerMap = getEventListenerMap(TIM);
  if (!eventListenerMap[type]) return;

  for (const cb of eventListenerMap[type]) {
    if (typeof cb === 'function') {
      cb.call({ tim }, event, tim);
    }
  }
}

export function watchIMEvent({ tim, TIM }: {
  tim: TimInstanceType;
  TIM: TimType;
}) {
  const eventList = getEventList(TIM);

  eventList.forEach((type) => {
    const callbackFunc = function (event: string) {
      executeCallbacks({
        type,
        event,
        tim,
        TIM,
      });
    };
    tim.on(type, callbackFunc);
  });
}

export function setEventListener({ type, cb, TIM }: {
  type: string;
  cb: EventCallback;
  TIM: TimType;
}) {
  const eventListenerMap = getEventListenerMap(TIM);

  if (eventListenerMap[type]) {
    if (eventListenerMap[type].indexOf(cb) === -1) {
      eventListenerMap[type].push(cb);
    }
  } else {
    eventListenerMap[type] = [cb];
  }
}
