import { AxiosInstance } from "axios";
import { formatNumberShowZero, persianStringToEnglishString } from "nums2persian";
import { ValidationChain, ValidationEventArgs } from "../chainOfResponsibility";
import { EnumValidateState } from "../enums";
import { ElementFactory } from "../Page/ElementsOfFormFactory/ElementFactory";
import { IMainStateFactory } from "../Types";
import { Cach } from "./Cach";

export class NumberBoxFactory extends ElementFactory {
    public forceUpdate = () => { }
    #value: number | null;
    public get value() {
        return this.#value;
    }

    public get text(): string {
        if (typeof this.#value === 'number') {
            return formatNumberShowZero(this.#value).replace(',', ' , ');
        }
        return '';
    }

    public setValue = (value: string | null) => {
        if (value) {
            const newValue = persianStringToEnglishString(value);

            this.#value = +newValue;
        } else {
            this.#value = null;
        }
        this.refreshHasChange();
        Cach.setValue(this, this.#value);
        this.forceUpdate();
    };

    public deseriallize = (e?: number | null) => {
        this.clearData();
        if (e === null) {
            //do nothing
        } else if (e === undefined) {
            //do nothing
        } else {
            this.#value = e;
            this.#defaultValue = this.#value;
        }
        Cach.setValue(this, this.#value);
    }

    public clearData = () => {
        Cach.clear(this);
        this.#value = null;
        this.#defaultValue = null;
        this.validation = true;
        this._hasChange = false;
    }

    #defaultValue: number | null;
    public get defaultValue() {
        return this.#defaultValue;
    }

    public focusToElement = () => {
        this.mainStateFactory.elementsOfForm.focuseToThisElement(this);
    }

    constructor(
        _mainStateFactory: IMainStateFactory,
        _fieldName: string,
        _dispose: () => void,
        public caption: string,
        public disabled: boolean,
        public readonly: boolean,
        public required: boolean,
        public minLength: number | null,
        public maxLength: number | null,
        public showHasChangeFlag: boolean,
        public dirLeftToRight: boolean,
        public placeHolder?: string,
        public tabIndex?: number,
        initialValue?: number,
        payLoadKey?: string,
        responseKey?: string,
        history?: {
            key: string,
            axios: (controllerPath: string) => AxiosInstance,
            controllerPath: string,
            actionPath?: string,
        }
    ) {
        super(_mainStateFactory, _fieldName, _dispose, payLoadKey, responseKey, history);

        if (typeof initialValue === 'number') {
            this.#defaultValue = initialValue;
            this.#value = initialValue;
        } else {
            this.#defaultValue = null;
            this.#value = null;
        }

        if (Cach.isCached(this)) {
            const cach = Cach.getCached(this);
            this.#value = cach.value;
            this.validation = cach.validation;
            this._hasChange = cach.hasChange;
        }
    }

    public restartDefaultValue = () => {
        this.#defaultValue = this.value;
        this.refreshHasChange();
    };

    public refreshHasChange = () => {
        if (this.showHasChangeFlag) {
            this._hasChange = this.defaultValue !== this.#value;
        }
    };

    public validate = () => {
        var validationChain = new ValidationChain();

        validationChain.validators.add(this.validateNormal);
        validationChain.validators.add(this.validateRequired);
        validationChain.validators.add(this.validateMinLength);
        validationChain.validators.add(this.validateMaxLength);

        this.validation = validationChain.validate();
    }

    private validateNormal = (_eventArgs: ValidationEventArgs) => { };
    private validateRequired = (eventArgs: ValidationEventArgs) => {
        if (this.required) {
            if (!this.value) {
                eventArgs.error = 'اطلاعاتی وارد نشده است';
                eventArgs.state = EnumValidateState.empty;
                eventArgs.cancel = true;
            }
        }
    };
    private validateMinLength = (eventArgs: ValidationEventArgs) => {
        if (this.minLength) {
            if (typeof this.value !== 'string' || this.value === '') {
                if (this.required) {
                    eventArgs.error = `اطلاعاتی وارد نشده  است. حداقل طول مجاز: ${this.minLength}`;
                    eventArgs.state = EnumValidateState.maxLength;
                    eventArgs.cancel = true;
                }
            } else if (this.value < this.minLength) {
                eventArgs.error = `طول مقدار وارد شده کمتر از مقدار مجاز میباشد. حداقل طول مجاز:  ${this.minLength}`;
                eventArgs.state = EnumValidateState.maxLength;
                eventArgs.cancel = true;
            }
        }
    };
    private validateMaxLength = (eventArgs: ValidationEventArgs) => {
        if (this.maxLength) {
            if (this.value && this.value > this.maxLength) {
                eventArgs.error = `طول مقدار وارد شده بیشتر از مقدار مجاز میباشد. حداکثر طول مجاز: ${this.maxLength}`;
                eventArgs.state = EnumValidateState.maxLength;
                eventArgs.cancel = true;
            }
        }
    };

    isValueEmpty = () => {
        return typeof this.#value === 'string' && this.#value !== '';
    }
    isValueNotEmpty = () => {
        return !this.isValueEmpty();
    }
}