import { AxiosError, AxiosInstance, AxiosResponse } from "axios";
import { persianStringToEnglishString } from "nums2persian";
import { EnumValidateState } from "../../enums";
import { ElementFactory } from "../../Page/ElementsOfFormFactory/ElementFactory";
import { IMainStateFactory } from "../../Types";
import { Cach } from "../Cach";
import { SIMPLECODE } from "amisa-paths";
import { useAxios, useUrls } from "../../AmisaAuth/Models/StorageManager/TokenInfo";

export type IResultOfValidate = true | [string, EnumValidateState];
export type ISimpleCodeState =
    | 'clear'
    | 'ok'
    | 'newCode';


type IResultType = null | 0 | 1;

interface IResponse {
    data: { id: number | null, code: number, name: string, nahveGimatGozari: number }
    isSuccess: boolean
    result: IResultType;
}

export class SimpleCodeFactory extends ElementFactory {
    public urls: SIMPLECODE;
    public apiAxios: AxiosInstance;
    public forceUpdate = () => { };
    public get any(): any {
        return this;
    }

    public focusToElement = () => {
        this.mainStateFactory.elementsOfForm.focuseToThisElement(this);
    }
    public showListView?: () => void;

    public name: string = '';
    public id: number | null = null;

    private refreshAllfromOfMainCode(_data: any) {
        // if (this.isMainCodeOfPage) {
        //     this.pageData.ValidatingControl.controls.forEach((property) => {
        //         const control = this.pageData.selfState[property.propertyName];

        //         if (control.keyOfJSON &&
        //             control.propertyName &&
        //             control !== this) {
        //             // deserializeFormControlFromMainCodeNew(data, control, this.pageData.selfState);

        //             if (control.onChangePropertyName) {
        //                 const onChangePropertyName = control[control.onChangePropertyName];
        //                 onChangePropertyName && onChangePropertyName(control);
        //             }
        //         }
        //     });

        //     this.pageData.TouchingControl.resetAllTouched();
        //     this.pageData.ChangingControl.resetAllChangeNew();
        //     this.pageData.Eventing.trigger('change');
        // }
    }

    private setValidationState = (result: IResultType): void => {
        this.codeValueState = result === null ? 'ok'
            : result === 0 ? 'newCode'
                : 'clear';
    }

    public codeWaitForLoad: null | string = null;
    private timerForLoad: NodeJS.Timeout | null = null;
    private clearTimerForLoad = () => {
        if (this.timerForLoad) {
            clearTimeout(this.timerForLoad);
        }
    };
    public getCodeData = () => {
        this.clearTimerForLoad();

        this.timerForLoad = setTimeout(() => {
            this.codeWaitForLoad = this.text;
            this.getCodeDataAxios();
        }, 500)

    }
    private getCodeDataAxios = () => {
        if (this.codeWaitForLoad === '') {
            this.clearData();
            return;
        }

        this.forceUpdateSpinner();
        this.apiAxios.get(`${this.urls.get}/${this.codeWaitForLoad}`)
            .then((response: AxiosResponse<IResponse>): void => {
                if (response.data.isSuccess) {
                    this.name = response.data.data.name;
                    this.id = response.data.data.id;
                    this.setValidationState(response.data.result);
                    // this.pageData.Eventing.trigger('form.GetNewCodeSuccessFull', response.data.data);
                    this.validate();
                    Cach.setValue(this, { name: this.name, id: this.id, codeValueState: this.codeValueState, code: this.code, text: this.text });
                    this.refreshAllfromOfMainCode(response.data.data);
                    this.codeWaitForLoad = null;
                    this.forceUpdate();
                } else {
                    console.error('some thing went wrong');
                    this.forceUpdate();
                }
            })
            .catch((error: AxiosError): void => {
                console.error('some thing went wrong : ', error);
                this.forceUpdate();
            });


    }

    ///state that get from server data
    public codeValueState: ISimpleCodeState = 'clear';

    public childCount = 0;

    validate = (): IResultOfValidate => {
        if (this.required && !this.code) {
            // 'namingNotImplement'
            this.validation = [`${this.caption} وارد نشده است`, EnumValidateState.empty];
            return this.validation;
        }
        this.validation = true;
        return this.validation;
    }

    #defaultValue: null | number = null;

    restartDefaultValue = () => {
        this.#defaultValue = this.code;
        this.refreshHasChange();
    }
    refreshHasChange = () => {
        if (this.showHasChangeFlag) {
            this._hasChange = this.#defaultValue !== this.#code;
        }
    }

    #code: number | null = null;
    #text: string | null = null;
    get text(): string {
        return this.#text || '';
    }
    setText(text: string) {
        this.#text = text;
        this.forceUpdate();
    }

    public get value() {
        return this.#code;
    }

    get code(): number {
        return this.#code || 0;
    }
    setValue(code: number) {
        this.#code = code;
        Cach.setValue(this, { name: this.name, id: this.id, codeValueState: this.codeValueState, code: this.code, text: this.text });
        this.forceUpdate();
    }
    public deseriallize = (e?: number | null) => { }

    public clearData = () => {
        Cach.clear(this);
        this.#code = null;
        this.#text = '';
        this.#defaultValue = null;
        this.validation = true;
        this._hasChange = false;

        this.codeValueState = 'clear';
        this.childCount = 0;

        this.forceUpdate();
    }
    constructor(
        _mainStateFactory: IMainStateFactory,
        _fieldName: string,
        _dispose: () => void,
        urls: SIMPLECODE,
        public isMainCodeOfPage: boolean,
        public required: boolean,
        public caption: string,
        public showHasChangeFlag: boolean,
        public tabIndex?: number,
        payLoadKey?: string,
        responseKey?: string,
        history?: {
            key: string,
            axios: (controllerPath: string) => AxiosInstance,
            controllerPath: string,
            actionPath?: string,
        }
    ) {
        super(_mainStateFactory, _fieldName, _dispose, payLoadKey, responseKey, history);
        this.urls = urls;
        this.apiAxios = useAxios(this.urls);

        if (Cach.isCached(this)) {
            const cach = Cach.getCached(this);
            this.name = cach.value.name;
            this.id = cach.value.id;
            this.codeValueState = cach.value.codeValueState;
            this.#code = cach.value.code;
            this.#text = cach.value.text;
            this.validation = cach.validation;
            this._hasChange = cach.hasChange;
        }
    }

    public forceUpdateSpinner = () => { }

    public onChangeHandlerElement = (element: HTMLInputElement) => {
        const valueNotPersian = element.value;
        this.onChangeHandlerCode(valueNotPersian);

    }

    public onChangeHandlerCode = (code: string) => {
        const value = persianStringToEnglishString(code, false);
        this.#code = +value;

        this.setText(value);
    }
}

