type Callback = (...args: any) => void;

export type PageEventType =
  | 'gridView.wasLoaded-waitForKeyDown'
  | 'gridView.onRowsChanged'
  | 'gridView.onSelectCurrentCellChange'
  | 'gridView.past.rows'
  | 'gridView.show.summery.rows'
  | 'gridView.show.formulaByCTRL'
  | 'gridView.show.formulaByALT'
  | 'gridView.columns.visibility.change'
  | 'gridView.end.columns.prepare'
  | 'gridView.copy.cell.value'
  | 'gridView.formula.change'
  | 'context.menu.end.items.prepare'
  | 'form.F1Button'
  | 'form.F2Button'
  | 'form.F3Button'
  | 'form.F4Button'
  | 'form.F5Button'
  | 'form.F6Button'
  | 'form.F7Button'
  | 'form.F8Button'
  | 'form.F9Button'
  | 'form.F10Button'
  | 'form.F11Button'
  | 'form.F12Button'
  | 'form.acceptButton'
  | 'form.spaceButton'
  | 'form.cancelButton'
  | 'form.newButton'
  | 'form.editButton'
  | 'form.viewButton'
  | 'form.deleteButton'
  | 'form.printButton'
  | 'form.printCrystalButton'
  | 'form.exportToExcelButton'
  | 'form.deleteReport'
  | 'form.addNewCustomReportButton'
  | 'form.editCustomReportButton'
  | 'form.deleteButtonRow'
  | 'form.nextButton'
  | 'form.backButton'
  | 'form.select.columns'
  | 'form.context.menu'
  | 'form.goto.next.pageButton'
  | 'form.goto.previous.pageButton'
  | 'form.nextSameLevelButton'
  | 'form.backSameLevelButton'
  | 'form.waitLoading'
  | 'form.wasLoaded'
  | 'form.printwasLoaded'
  | 'form.wasErrored'
  | 'form.controlValueNotValid'
  | 'form.control.new.add'
  | 'form.disabled'
  | 'form.enabled'
  | 'form.getActive'
  | 'form.fieldset.getActive'
  | 'form.hasChangeOnTabs'
  | 'form.change'
  | 'form.reset.values'
  | 'form.SuccessFullOtherCommand'
  | 'form.SuccessFull'
  | 'form.AutoFirstLoadSuccessFull'
  | 'form.SaveSuccessFull'
  | 'form.GetNewCodeSuccessFull'
  | 'form.DeleteSuccessFull'
  | 'change'
  | 'stack.add.new'
  | 'stack.get.active'
  | 'stack.will.onmount'
  | 'stack.closed'
  | 'stack.icon.refresh'
  | 'stack.header.text.refresh'
  | 'StructuralCode.SaveSuccessFull'
  | 'StructuralCode.GetNewCodeSuccessFull'
  | 'StructuralCode.DeleteSuccessFull'
  | 'SimpleCode.SaveSuccessFull'
  | 'SimpleCode.GetNewCodeSuccessFull'
  | 'SimpleCode.DeleteSuccessFull'
  | 'message.AreYouSureToDeletThisCode'
  | 'message.AreYouSureToDeletThisRow'
  | 'message.ThereAreSomeErrorYouCanNotSaveForm'
  | 'message.InvalidArgument'
  | 'message.SomeThingWentWrong'
  | 'message.ThereIsNotAnyChangeForSave'
  | 'message.ThereIsSomeChangeBeforeCancel'
  | 'message.AreYouSureToNewCode'
  | 'message.SuccessFull'
  | 'SuccessFull'
  | 'SaveSuccessFull'
  | 'SaveCommonFormSuccessFull'
  | 'form.control.simulate.keyDown'
  | 'key.down'
  | 'key.down.space'
  | 'field.set.will.onmount'
  | 'field.set.mounted'
  | 'factory.class.will.unmount'
  | 'factory.class.filter.change'
  ;

export type IControlSimulateKey = 'ControlEnter' | 'Space' | 'AlphbetKeys';

export class Events {
  events: { [key: string]: Callback[] } = {};

  onSimulateKeyDown = <T>(
    key: IControlSimulateKey,
    propertyName: keyof T,
    callBack: Callback
  ) => {
    this.on(
      ('form.control.simulate.keyDown' + key.toString() + propertyName.toString()) as any,
      callBack
    );
  };
  removeOnSimulateKeyDown = <T>(
    key: IControlSimulateKey,
    propertyName: keyof T
  ): void => {
    this.removeOn(
      ('form.control.simulate.keyDown' + key.toString() + propertyName.toString()) as any
    );
  };
  SimulateKeyDown = <T>(
    key: IControlSimulateKey,
    propertyName: keyof T,
    ...args: any
  ) => {
    this.trigger(
      ('form.control.simulate.keyDown' + key.toString() + propertyName.toString()) as any,
      args
    );
  };

  on = (eventName: PageEventType, callBack: Callback): void => {
    const handlers = this.events[eventName] || [];
    handlers.push(callBack);
    this.events[eventName] = handlers;
  };
  removeOn = (eventName: PageEventType): void => {
    this.events[eventName] = [];
  };



  onControl = (
    eventName: PageEventType,
    propertyName: any,
    callBack: Callback
  ) => {
    this.on((eventName + propertyName) as any, callBack);
  };
  triggerControl = (
    eventName: PageEventType,
    propertyName: any,
    ...args: any
  ) => {
    this.trigger((eventName + propertyName) as any, args);
  };
  removeOnControl = (eventName: PageEventType, propertyName: any) => {
    this.removeOn((eventName + propertyName) as any);
  };

  trigger = (eventName: PageEventType, ...args: any): void => {
    const handlers = this.events[eventName];

    if (!handlers || handlers.length === 0) {
      return;
    }

    handlers.forEach((callback) => {
      callback.apply(null, args);
    });
  };
}
