import { AxiosInstance } from "axios";
import { isValid, onChangeInputDateBoxShamsiHandleValue, ReturnMiladyDate } 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 type IResultOfValidate = true | [string, EnumValidateState];
export type IDatePickerState =
    | 'clear'
    | 'ok'
    | 'dirty';



type ITextState = 'miladi' | 'shamsi';

export class DateBoxFactory extends ElementFactory {
    public forceUpdate = () => { };
    public readonly?: boolean;
    public dirLeftToRight?: boolean;

    public get any(): any {
        return this;
    }
    public showDatePicker?: () => void;

    public focusToElement = () => {
        this.mainStateFactory.elementsOfForm.focuseToThisElement(this);
    }

    public validation: IResultOfValidate = true;
    public validationState: IDatePickerState = 'clear';
    public minDate: string | undefined;
    public maxDate: string | undefined;

    private validateNormal = (eventArgs: ValidationEventArgs) => {
        if (typeof this.value === 'string' && this.value !== '') {
            if (this.value.split('/').length === 3) {
                if (!isValid(this.value)) {
                    eventArgs.error = 'تاریخ وارد شده معتبر نیست';
                    eventArgs.state = EnumValidateState.invalidValue;
                    eventArgs.cancel = true;
                }
            } else {
                eventArgs.error = 'مقدار تاریخ بدرستی وارد نشده است';
                eventArgs.state = EnumValidateState.invalidValue;
                eventArgs.cancel = true;
            }
        }
    };
    private validateRequired = (eventArgs: ValidationEventArgs) => {
        if (this.required) {
            if (this.value === null || this.value === undefined || (typeof this.value !== 'string' || this.value === '')) {
                eventArgs.error = 'تاریخ وارد نشده است';
                eventArgs.state = EnumValidateState.empty;
                eventArgs.cancel = true;
            }
        }
    };
    private validateMinDate = (eventArgs: ValidationEventArgs) => {
        if (this.minDate) {
            if (!this.value) {
                eventArgs.error = `تاریخ وارد نشده  است. حداقل تاریخ مجاز: ${this.minDate}`;
                eventArgs.state = EnumValidateState.minValue;
                eventArgs.cancel = true;
            } else if (this.value < this.minDate) {
                eventArgs.error = `تاریخ مقدار وارد شده کمتر از مقدار مجاز میباشد. حداقل تاریخ مجاز:  ${this.minDate}`;
                eventArgs.state = EnumValidateState.minValue;
                eventArgs.cancel = true;
            }
        }
    };
    private validateMaxDate = (eventArgs: ValidationEventArgs) => {
        if (this.maxDate) {
            if (this.value && this.value > this.maxDate) {
                eventArgs.error = `تاریخ مقدار وارد شده بیشتر از مقدار مجاز میباشد. حداکثر تاریخ مجاز: ${this.maxDate}`;
                eventArgs.state = EnumValidateState.maxLength;
                eventArgs.cancel = true;
            }
        }
    };


    isValueEmpty = () => {
        return typeof this.#value === 'string' && this.#value !== '';
    }
    isValueNotEmpty = () => {
        return !this.isValueEmpty();
    }

    validate = () => {
        var validationChain = new ValidationChain();

        validationChain.validators.add(this.validateNormal);
        validationChain.validators.add(this.validateRequired);
        validationChain.validators.add(this.validateMinDate);
        validationChain.validators.add(this.validateMaxDate);

        this.validation = validationChain.validate();
    };

    public currentTextState: ITextState = 'shamsi';
    public changeCurrentTextState = () => {
        if (this.currentTextState === 'shamsi') {
            this.currentTextState = 'miladi';
            if (this.#value) {
                this.text = ReturnMiladyDate(this.#value);
            }
        } else {
            this.currentTextState = 'shamsi';
            this.text = this.#value || '';
        }
        this.forceUpdate();
    }

    #text: string = '';
    public get text(): string {
        return this.#text;
    }
    public set text(v: string) {
        this.#text = v;
    }


    #defaultValue: null | string;
    public get defaultValue() {
        return this.#defaultValue;
    }

    restartDefaultValue = () => {
        this.#defaultValue = this.#value;
        this.refreshHasChange();
    }
    refreshHasChange = () => {
        if (this.showHasChangeFlag) {
            this._hasChange = this.#defaultValue !== this.#value;
        }
    }

    #value: string | null;
    get value(): string {
        return this.#value || '';
    }
    setValue(value: string) {
        this.#value = value;
        if (this.currentTextState === 'shamsi') {
            this.#text = this.#value;
        } else {
            this.#text = ReturnMiladyDate(this.#value);
        }
        this.validate();
        Cach.setValue(this, value);
        this.onChange && this.onChange(this);
        this.forceUpdate();
    }
    public deseriallize = (e?: string | null) => {
        this.clearData();
        if (e === null) {
            //do nothing
        } else if (e === undefined) {
            //do nothing
        } else if (typeof e === 'object') {
            this.#value = JSON.stringify(e);
            this.#defaultValue = this.#value;
            if (this.currentTextState === 'shamsi') {
                this.#text = this.#value;
            } else {
                this.#text = ReturnMiladyDate(this.#value);
            }
        } else {
            this.#value = e;
            this.#defaultValue = this.#value;
            if (this.currentTextState === 'shamsi') {
                this.#text = this.#value;
            } else {
                this.#text = ReturnMiladyDate(this.#value);
            }
        }
        Cach.setValue(this, this.#value);
    }

    public clearData = () => {
        Cach.clear(this);
        this.#value = null;
        this.#defaultValue = null;
        this.#text = '';
        this.validation = true;
        this._hasChange = false;
        this.forceUpdate();
    }

    public placeHolder: string;
    constructor(
        _mainStateFactory: IMainStateFactory,
        _fieldName: string,
        _dispose: () => void,
        public required: boolean,
        public showHasChangeFlag: boolean,
        public caption?: string,
        _placeHolder?: string,
        public tabIndex?: number,
        initialValue?: string,
        payLoadKey?: string,
        responseKey?: string,
        history?: {
            key: string,
            axios: (controllerPath: string) => AxiosInstance,
            controllerPath: string,
            actionPath?: string,
        },
        public onChange?: ((dateBoxFactory: DateBoxFactory) => void)
    ) {
        super(_mainStateFactory, _fieldName, _dispose, payLoadKey, responseKey, history);

        if (typeof initialValue === 'string') {
            this.#defaultValue = initialValue;
            this.#value = initialValue;
            if (this.currentTextState === 'shamsi') {
                this.#text = this.#value;
            } else {
                this.#text = ReturnMiladyDate(this.#value);
            }
        } else {
            this.#defaultValue = null;
            this.#value = null;
        }

        if (Cach.isCached(this)) {
            const cach = Cach.getCached(this);
            this.#value = cach.value;

            if (this.#value) {
                if (this.currentTextState === 'shamsi') {
                    this.#text = this.#value;
                } else {
                    this.#text = ReturnMiladyDate(this.#value);
                }
            }
            this.validation = cach.validation;
            this._hasChange = cach.hasChange;
        }

        if (typeof _placeHolder === 'string') {
            this.placeHolder = _placeHolder;
        }
        else {
            this.placeHolder = '####/##/##';
        }
    }

    changeHandler = (element: HTMLInputElement) => {
        if (this.currentTextState === 'miladi') {
            return;
        }

        this.setValue(onChangeInputDateBoxShamsiHandleValue(element.value, this.value));
    }

}

