import { AxiosInstance } from "axios";
import { EnumValidateState } from "../enums";
import { ElementFactory } from "../Page/ElementsOfFormFactory/ElementFactory";
import { IMainStateFactory } from "../Types";
import { Cach } from "./Cach";
import { StructrulCodeFactory } from "./StructructrulCode/StructrulCodeFactory";

export type IResultOfValidate = true | [string, EnumValidateState];
export type ISelectCustomerState =
    | 'clear'
    | 'ok'
    | 'dirty'
    | 'withoutParent'
    | 'newCode';

export type ISelectCustomerTypeOfCode = 'actually' | 'potential';

export type ISelectCustomerUseCaseType = 'MainPageCode' | 'Filter' | 'SelectCode';

export interface IFullName {
    id: number;
    code: string;
    name: string;
}

export class SelectCustomerFactory extends ElementFactory {
    public forceUpdate = () => { };

    public get any(): any {
        return this;
    }

    public swapTypeOfCode = () => {
        this.clearData();
        if (this.typeOfCode === 'actually') {
            this.typeOfCode = 'potential';
        } else {
            this.typeOfCode = 'actually';
        }
    }

    public focusToElement = () => {
        this.mainStateFactory.elementsOfForm.focuseToThisElement(this);
        this.element?.focus();
    }

    public showPotentialListView?: () => void;
    public showListView?: (value?: string) => void;

    private setCachedData = () => {
        Cach.setValue(this, {
            fullName: this.fullName,
            childCount: this.childCount,
            name: this.name,
            typeOfCode: this.typeOfCode,
            id: this.id,
            codeValueState: this.codeValueState,
            code: this.code,
            text: this.text
        });
    }
    public clearData = () => {
        Cach.clear(this);
        this.#code = null;
        this.#text = null;
        this._defaultValue = null;

        this.fullName = [];

        this.name = '';
        this.codeValueState = 'clear';
        this.childCount = 0;
        this.validation = true;
    }

    public id: number | null = null;
    public fullName: IFullName[] = [];
    public name: string = '';
    public typeOfCode: ISelectCustomerTypeOfCode = 'potential';

    ///state that get from server data
    public codeValueState: ISelectCustomerState = 'clear';

    public childCount = 0;

    validate = (): IResultOfValidate => {
        if (this.required && !this.code) {
            // 'namingNotImplement'
            this.validation = [`${this.caption} وارد نشده است`, EnumValidateState.empty];
            return this.validation;
        } else if (this.codeValueState === 'dirty') {
            this.validation = [`طول ${this.caption} وارد شده معتبر نیست`, EnumValidateState.invalidLength];
            return this.validation;
        } else if (this.codeValueState === 'withoutParent') {
            this.validation = [`${this.caption} وارد شده سرفصل بالاتر ندارد`, EnumValidateState.withoutParent];
            return this.validation;
        } else if (this.onlyLastLevel && this.codeValueState === 'newCode') {
            this.validation = [`${this.caption} وارد شده وجود ندارد`, EnumValidateState.withoutParent];
            return this.validation;
        } else if (this.onlyLastLevel && this.childCount > 0) {
            this.validation = [`${this.caption} وارد شده سرفصل جزء دارد`, EnumValidateState.hasChildren];
            return this.validation;
        }
        this.validation = true;
        return this.validation;
    }

    #code: string | null = null;
    #text: string | null = null;
    get text(): string {
        return this.#text || '';
    }
    setText(text: string) {
        this.#text = text;
        this.setCachedData();
        this.forceUpdate();
    }

    public get value() {
        return this.#code;
    }

    get code(): string {
        return this.#code || '';
    }
    setValue(code: string) {
        this.#code = code;
        this.setCachedData();
        this.forceUpdate();
    }
    public deseriallize = (e?: string | null) => { }

    private _defaultValue: null | string = null;

    restartDefaultValue = () => {
        this._defaultValue = this.code;
        this.refreshHasChange();
    }
    refreshHasChange = () => {
        if (this.showHasChangeFlag) {
            this._hasChange = this._defaultValue !== this.#code;
        }
    }

    constructor(
        _mainStateFactory: IMainStateFactory,
        _fieldName: string,
        _dispose: () => void,
        public useCaseType: ISelectCustomerUseCaseType,
        public required: boolean,
        public onlyLastLevel: boolean,
        public caption: string,
        public structrulCodeFactory: StructrulCodeFactory,
        public axiosData: {
            axios: (controllerPath: string) => AxiosInstance;
            controllerPotentialPath: string;
            controllerActuallyPath: string;
            listPotentialViewActionPath?: string;
            listActuallyActionPath?: string;
        },
        public showHasChangeFlag: boolean,
        public tabIndex?: number,
        payLoadKey?: string,
        responseKey?: string,
        public onChange?: (e: SelectCustomerFactory) => void,
    ) {
        super(_mainStateFactory, _fieldName, _dispose, payLoadKey, responseKey);

        if (Cach.isCached(this)) {
            const cach = Cach.getCached(this);
            this.name = cach.value.name;
            this.typeOfCode = cach.value.typeOfCode;
            this.fullName = cach.value.fullName;
            this.childCount = cach.value.childCount;
            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 = () => { }
}