type Callback = (...args: any) => void;

export type EventType =
  | 'change'
  | 'error'
  | 'userLoginStart'
  | 'userLoginLoadData'
  | 'userLoginSuccess'
  | 'userSignUpStart'
  | 'userTokenExpired'
  | 'getAllDataFaild'
  | 'loadAssetsStart'
  | 'loadAssetsFail'
  | 'loadAssetsSuccess'
  | 'loadLanguagesStart'
  | 'loadLanguagesFail'
  | 'loadLanguagesSuccess'
  | 'loadMenuItemsStart'
  | 'loadMenuItemsFail'
  | 'loadMenuItemsSuccess'
  | 'loadNamingStart'
  | 'loadNamingFail'
  | 'loadNamingSuccess'
  | 'loadSettingStart'
  | 'loadSettingFail'
  | 'loadSettingSuccess'
  | 'loadWidthsStart'
  | 'loadWidthsFail'
  | 'loadWidthsSuccess'
  | 'ChangeActiveDataSuccess'
  | 'addNewFinancialPeriodSuccessFully'
  | 'dashboardDataShowStateChange'
  | 'changeTheme'
  | 'addNewTab'
  | 'selectTab'
  | 'closeTab'
  | 'helpState'
  | 'hasChangeOnTabs'
  | 'showWaitingModal'
  | 'closeWaitingModal'
  | 'addNewModalPage'
  | 'addNewModal'
  | 'closeModal'
  | 'addNewPopupPage'
  | 'addNewPopup'
  | 'closePopup'
  | 'changeSelectedSystem'
  | 'changeSelectedMenuItem'
  | 'restartMenuItem'
  | 'initialFilterRefValue'
  | 'mensuringWidthSize'
  | 'progressBarChange'
  | 'toggle';

export interface IEvents {
  eventName: string;
  callback: Callback[];
  pageKey: string;
}

export class Events {
  events: IEvents[] = [];

  on = (pageKey: string, eventName: EventType, callBack: Callback): void => {
    const handlers = this.events.find(
      (i) => i.eventName === eventName && i.pageKey === pageKey
    );
    if (handlers) {
      handlers.callback.push(callBack);
    } else {
      const newHandler: IEvents = {
        eventName: eventName,
        pageKey: pageKey,
        callback: [],
      };
      newHandler.callback.push(callBack);
      this.events.push(newHandler);
    }
  };

  remove = (pageKey: string, eventName: EventType): void => {
    this.events = this.events.filter(
      (i) => !(i.eventName === eventName && i.pageKey === pageKey)
    );
  };
  removeAllForThisPage = (pageKey: string): void => {
    this.events = this.events.filter((i) => i.pageKey !== pageKey);
  };

  trigger = (eventName: EventType, ...args: any): void => {
    const handlers = this.events.filter((i) => i.eventName === eventName);

    if (handlers && handlers.length > 0) {
      handlers.forEach((handler) => {
        if (handler && handler.callback && handler.callback.length > 0) {
          handler.callback.forEach((callback) => {
            callback.apply(null, args);
          });
        }
      });
    }
  };
}
