import { Clipboarding } from './Clipboard';
import { INaming } from './NamingCaption';
import { Argument, IMainStateFactory, OfficialAttacheFormsType } from '..';
import { SettingInfo } from './AmisaAuth/Models/SettingInfo';
import { ModalFactory } from './ComponentFactory/ModalFactory';
import { AuthFactory } from './AmisaAuth/AuthFactory';
import { IPopupMouseLocation, PopupFactory } from './ComponentFactory/PopupFactory';
import { LazyLoadFactory } from './LazyLoadFactory';
import { PageLoadByKey } from './PageLoadByKey';
import { SendByLetterFactory } from './ComponentFactory/SendByLetterFactory';
import { UserInfo } from './AmisaAuth/Models/UserInfo/UserInfo';
import { FiscalYearsInfo } from './AmisaAuth/Models/FiscalYearsInfo/FiscalYearsInfo';
import { SubSystemsInfo } from './AmisaAuth/Models/SubSystemsInfo/SubSystemsInfo';
import { TokenInfo } from './AmisaAuth/Models/StorageManager/TokenInfo';
import { Paths } from 'amisa-paths';

export type TThemeMode = 'light' | 'dark';
export class MainStateManager {
  public domDirection: 'ltr' | 'rtl' = 'rtl';
  public domIsDark: boolean = false;
  public get any() {
    return this as any;
  }


  #authFactory?: AuthFactory;
  public get authFactory(): AuthFactory {
    return this.#authFactory!;
  }
  #baseUrl?: string;
  public get baseUrl(): string {
    return this.#baseUrl!;
  }
  #projectKey?: string;
  public get projectKey(): string {
    return this.#projectKey!;
  }
  #pathManager?: Paths;
  public get pathManager(): Paths {
    return this.#pathManager!;
  }
  #userInfo?: UserInfo;
  public get userInfo(): UserInfo {
    return this.#userInfo!;
  }
  #settingInfo?: SettingInfo;
  public get settingInfo(): SettingInfo {
    return this.#settingInfo!;
  }
  #fiscalYearsInfo?: FiscalYearsInfo;
  public get fiscalYearsInfo(): FiscalYearsInfo {
    return this.#fiscalYearsInfo!;
  }
  #subSystemsInfo?: SubSystemsInfo;
  public get subSystemsInfo(): SubSystemsInfo {
    return this.#subSystemsInfo!;
  }
  #tokenInfo?: TokenInfo;
  public get tokenInfo(): TokenInfo {
    return this.#tokenInfo!;
  }


  /* @internal */
  public initializeServices = (baseUrl: string, projectKey: string, pathManager: Paths) => {
    this.#baseUrl = baseUrl;
    this.#projectKey = projectKey;
    this.#pathManager = pathManager;
    this.#userInfo = new UserInfo(this);
    this.#tokenInfo = new TokenInfo(this);
    this.#settingInfo = new SettingInfo(this);
    this.#fiscalYearsInfo = new FiscalYearsInfo(this);
    this.#subSystemsInfo = new SubSystemsInfo(this);
    this.#authFactory = new AuthFactory(this);
  }

  public lazyLoadFactory: LazyLoadFactory = new LazyLoadFactory(this);
  public pageLoadKeyFactory: PageLoadByKey = new PageLoadByKey(this);

  public Clipboarding = new Clipboarding(this);

  public forceUpdate = () => { };
  public forceUpdateToShowFullScreenWaittingSpinner = (_mainState: IMainStateFactory, _onClosedModal?: () => void) => { };
  public forceUpdateToShowSomeThingWentWrong = (_mainState: IMainStateFactory, _onClosedModal?: () => void) => { };
  public forceUpdateToShowError = (_mainState: IMainStateFactory, _erro: Error, _onClosedModal?: () => void) => { };
  public forceUpdateToShowThereAreSomeErrorYouCanNot = (_mainState: IMainStateFactory, _countOfError: number, _onClosedModal?: () => void) => { };
  public forceUpdateToShowInvalidArgument = (_mainState: IMainStateFactory, _description: string, _onClosedModal?: () => void) => { };
  public forceUpdateToShowSuccessFull = (_mainState: IMainStateFactory, _caption?: string, _text?: string, _description?: string, _onClosedModal?: () => void) => { };
  public forceUpdateToShowAreYouSureDelete = (_mainState: IMainStateFactory, _onDeleteClick: () => void, _caption?: string, _text?: string, _description?: string) => { };
  public forceUpdateToShowThereIsNotAnyChangeForSave = (_mainState: IMainStateFactory, _onClosedModal?: () => void) => { };
  public forceUpdateToShowAttachedFiles = (
    _mainState: IMainStateFactory,
    _argument: string | number | object | undefined,
    _axiosData: {
      controllerPath: string;
      acceptPath?: string;
      getListPath?: string;
      getByIdPath?: string;
      deletePath?: string;
    },
    _caption?: string,
    _onClosedModal?: (() => void),
  ) => { };

  public sendByLetterForm?: SendByLetterFactory;
  public showSendByLetterForm = (type: OfficialAttacheFormsType, object: { id: number }) => {
    if (!this.sendByLetterForm) {
      this.sendByLetterForm = new SendByLetterFactory(this);
    }
    this.sendByLetterForm.addForm(type, object)
    this.forceUpdate();
  }
  public closeSendByLetterForm = () => {
    this.sendByLetterForm?.dispose();
    delete this.sendByLetterForm;
    this.forceUpdate();
  }


  public popups: PopupFactory[] = [];
  public showPopup = (mainState: IMainStateFactory, children: JSX.Element, e?: IPopupMouseLocation, onClosedPopup?: () => void) => {
    const popupFactory = new PopupFactory(mainState, children, e, onClosedPopup);
    mainState.elementsOfForm.popup = popupFactory;
    this.popups.push(popupFactory);
    this.forceUpdate();
  }
  public closePopup = (mainFactory: PopupFactory) => {
    this.popups = this.popups.filter(i => i !== mainFactory);
    mainFactory.popupRoot.removeChild(mainFactory.mainDivElement);
    mainFactory.popupRoot.removeChild(mainFactory.backdropDivElement);
    this.forceUpdate();
  }

  public modals: ModalFactory[] = [];

  public showModal = (mainState: IMainStateFactory, children: JSX.Element, isWaitingModal?: boolean, onClosedModal?: () => void, argumentClass?: Argument, cssClasses?: string) => {
    const modalFactory = new ModalFactory(mainState, children, isWaitingModal, onClosedModal, argumentClass, cssClasses);
    mainState.elementsOfForm.childModal = modalFactory;

    this.modals.push(modalFactory);

    this.forceUpdate();
  }
  public showFullScreenWaittingSpinner = (mainState: IMainStateFactory, onClosedModal?: () => void) => {
    this.forceUpdateToShowFullScreenWaittingSpinner(mainState, onClosedModal);
  }
  public showErrorMessageBox = (mainState: IMainStateFactory, error: Error, onClosedModal?: () => void) => {
    this.forceUpdateToShowError(mainState, error, onClosedModal);
  }
  public showThereAreSomeErrorYouCanNot = (mainState: IMainStateFactory, countOfError: number, onClosedModal?: () => void) => {
    this.forceUpdateToShowThereAreSomeErrorYouCanNot(mainState, countOfError, onClosedModal);
  }
  public showSomeThingWentWrong = (mainState: IMainStateFactory, onClosedModal?: () => void) => {
    this.forceUpdateToShowSomeThingWentWrong(mainState, onClosedModal);
  }
  public showInvalidArgumentMessageBox = (mainState: IMainStateFactory, description: string, onClosedModal?: () => void) => {
    this.forceUpdateToShowInvalidArgument(mainState, description, onClosedModal);
  }
  public showSuccessFullMessageBox = (mainState: IMainStateFactory, caption?: string, text?: string, description?: string, onClosedModal?: () => void) => {
    this.forceUpdateToShowSuccessFull(mainState, caption, text, description, onClosedModal);
  }
  public showAreYouSureDeleteMessageBox = (mainState: IMainStateFactory, onClickDelete: () => void, caption?: string, text?: string, description?: string) => {
    this.forceUpdateToShowAreYouSureDelete(mainState, onClickDelete, caption, text, description);
  }
  public showThereIsNotAnyChangeForSave = (mainState: IMainStateFactory, onClosedModal?: () => void) => {
    this.forceUpdateToShowThereIsNotAnyChangeForSave(mainState, onClosedModal);
  }
  public showAttachedFiles = (
    mainState: IMainStateFactory,
    argument: string | number | object | undefined,
    axiosData: {
      controllerPath: string;
      acceptPath?: string;
      getListPath?: string;
      getByIdPath?: string;
      deletePath?: string;
    },
    caption?: string,
    onClosedModal?: (() => void),
  ) => {
    this.forceUpdateToShowAttachedFiles(mainState, argument, axiosData, caption, onClosedModal);
  }

  public closeModal = (mainFactory: ModalFactory) => {
    this.modals = this.modals.filter(i => i !== mainFactory);
    mainFactory.modalRoot.removeChild(mainFactory.mainDivElement);
    mainFactory.modalRoot.removeChild(mainFactory.backdropDivElement);
    this.forceUpdate();
  }

  public history?: { push: (path: string) => void };
  public push = (path: string) => {
    if (this.history) {
      const push = this.history?.push;
      if (typeof push === 'function') {
        push(path);
      }
      else {
        console.error('push is not a function on history');
      }
    }
  }
  public signOut = () => {
    const authFactory = this.any['intializeAuthFactory_temp'];
    if (authFactory) {
      const signOut = authFactory.signOut;
      if (typeof signOut === 'function') {
        signOut();
      }
      else {
        console.error(`signOut in not function on signout`, signOut);
      }
    } else {
      console.error(`authFactory is undefined on signout`, authFactory);
    }
  }

  // generateTheme = () => {
  //   const option = this.Usering.userOptions.find(item => item.key === 'theme');
  //   if (option) {
  //     this._themeMode = 'dark';
  //   }
  // }

  private _themeMode: TThemeMode = 'light';
  public get themeMode(): TThemeMode {
    return this._themeMode;
  }

  public windowWidth = 0;
  public delayLayoutShowForMain?: boolean = undefined;

  public progressInitialize: boolean = false;
  public progressBarLoading: number = 0;


  setWindowWidth(windowWidth: number) {
    this.windowWidth = windowWidth;
  }
  public classEffect = '';
  public classEffectFooter = '';
  setOpacityDisplay(opacityDisplay: boolean) {
    this.classEffect = opacityDisplay ? 'opacity-display-show' : 'opacity-display-hide';
    this.classEffectFooter = opacityDisplay ? 'opacity-display-show-footer' : 'opacity-display-hide-footer';
  }


  public getCaptionNaming(caption: INaming): string {
    if (!caption) {
      return 'nothing';
    }

    if (typeof caption === 'string') {
      return caption;
    }

    if (caption instanceof Array) {
      if (caption.length === 2) {
        return caption[1];
      }
    }

    // if (caption instanceof CaptionNaming) {
    //   return (caption as any)[this.Languaging.languageSuffix];
    // }

    // if (typeof caption === 'object') {
    //   if (this.Languaging.languageSuffix in caption) {
    //     return (caption as any)[this.Languaging.languageSuffix];
    //   } else if ('FA' in caption) {
    //     return (caption as any)['FA'];
    //   } else if ('EN' in caption) {
    //     return (caption as any)['EN'];
    //   }
    // }

    return 'nothing';
  }
}