import { AxiosInstance, AxiosRequestConfig } from "axios";
import { IMainStateFactory, IResultOfValidate, MainStateManager } from "../..";
import { TokenInfo } from "../AmisaAuth/Models/StorageManager/TokenInfo";
import { ElementFactory } from "../Page/ElementsOfFormFactory/ElementFactory";
import { FileDownload } from "./FileDownload";


export class AttachedFilesFactory extends ElementFactory {
    restartDefaultValue = () => { };
    refreshHasChange = () => { };
    deseriallize = (jsonValue: any) => { };
    clearData = () => { };
    get value(): any {
        return this.files?.length || 0;
    }
    public forceUpdate = () => { };

    public get tokenInfo(): TokenInfo {
        return this.mainStateManager.tokenInfo;
    }
    public validation: IResultOfValidate = true;
    public validate = () => { }

    public get selectElement(): HTMLInputElement {
        return document.getElementById('input-attach-file-selector') as HTMLInputElement;
    };
    public element?: HTMLDivElement;

    public get hasChange(): boolean {
        return false;
    }

    #files: AttachedFile[] = [];
    public get files(): AttachedFile[] {
        return this.#files;
    }
    public addFiles = (file: File) => {
        const attached = new AttachedFile(file.name, file.size, '', file);
        this.#files.push(attached);
    }
    public clearFiles() {
        this.#files = [];
        this.forceUpdate();
    }
    public mainStateManager: MainStateManager;

    constructor(
        mainStateFactory: IMainStateFactory,
        fieldName: string,
        dispose: () => void,
        public axiosData: {
            axios: (controllerPath: string) => AxiosInstance,
            controllerPath: string,
            actionUploadPath: string,
            actionDownloadPath: string,
        },
        public caption: string,
        public maxLength: number | null,
        public maxSize: number | null,
        public placeHolder?: string,
        public tabIndex?: number,
        payLoadKey?: string,
        responseKey?: string
    ) {
        super(mainStateFactory, fieldName, dispose, payLoadKey, responseKey);
        this.mainStateManager = this.mainStateFactory.mainStateManager;
    }


    public save = (id: number) => {
        const header = this.tokenInfo.headerOfAxios.headers!;
        header["content-type"] = "multipart/fom-data";
        const formData = new FormData();
        this.files.filter(i => i.file !== undefined).forEach(file =>
            formData.append(file.name, file.file!, file.name)
        );
        return this.axiosData.axios(this.axiosData.controllerPath).post(`${this.axiosData.actionUploadPath}/${id}`, formData, { headers: header });
    }

    public download = (id: number, fileName: string) => {
        const header: AxiosRequestConfig = { responseType: 'blob', headers: { Authorization: `token ${this.tokenInfo.token}` } };

        this.axiosData.axios(this.axiosData.controllerPath).get(`${this.axiosData.actionDownloadPath}/${id}`, header)
            .then((res) => {
                FileDownload(res.data, fileName);
            }).catch(error => {
                this.mainStateFactory.elementsOfForm.showErrorMessageBox(error);
            })

    }
}
type IAttachedFileType =
    | 'excel'
    | 'pdf'
    | 'zip'
    | 'doc'
    | 'txt'
    | 'image'
    | 'others'
    ;

export class AttachedFile {
    public type: IAttachedFileType
    constructor(
        public name: string,
        public size: number,
        public tozihat: string,
        public file?: File,
        public id?: number,
    ) {
        if (name.includes('.sheet')) {
            this.type = 'excel';
        } else if (name.includes('.doc')) {
            this.type = 'doc';
        } else if (name.includes('imag')) {
            this.type = 'image';
        } else if (name.includes('pdf')) {
            this.type = 'pdf';
        } else if (name.includes('txt')) {
            this.type = 'txt';
        } else if (name.includes('rar') || name.includes('zip')) {
            this.type = 'zip';
        } else {
            this.type = 'others';
        }
    }
}

