import { HttpErrorResponse } from "@angular/common/http";
import { Pagination } from "@shared/models/pagination.model";

export class UtilHelper {
    static clone(model: any) {
        return $.extend(true, {}, model);
    }

    static cloneList(list: any) {
        return $.extend(true, [], list);
    }

    static unique(value: any, index: any, self: any) {
        return self.indexOf(value) === index;
    }

    static uniqBy(arr: any, predicate: string) {
        const cb = (o: any) => o[predicate];

        return [...arr.reduce((map: any, item: any) => {
            const key = cb(item);

            map.has(key) || map.set(key, item);

            return map;
        }, new Map()).values()];
    }

    static isFiltersApplied(options: Object, ignore?: number): boolean {
        const applied = Object.keys(options).map((key: string) => options[key]).filter((m: Object) => m).length;
        return typeof ignore === "number" ? (applied - ignore) > 0 : applied > 0;
    }

    static getCurrentItems(length: number, pagination: Pagination) {
        return length > 0
            ? ((Math.abs(pagination.totalItems) % pagination.pageSize) === length
                ? pagination.totalItems
                : length > 0
                    ? length * pagination.pageIndex
                    : 0)
            : 0;
    }

    static applyPagination(data: Array<any>, pagination: Pagination, status?: boolean) {
        const length = data ? data.length : 0;
        if (length > 0) {
            pagination.totalItems = data[0]["totalItems"];
            pagination.totalPages = Math.ceil(pagination.totalItems / pagination.pageSize);
            pagination.currentItems = ((Math.abs(pagination.totalItems) % pagination.pageSize) === length
                ? pagination.totalItems
                : length > 0
                    ? length * (status ? pagination.pageIndex + 1 : pagination.pageIndex)
                    : 0);
            pagination.currentPage = status ? pagination.pageIndex + 1 : pagination.pageIndex;
        }
    }
    static applyPaginationOnRoleBase(data: Array<any>, pagination: Pagination, status?: boolean) {
        const length = data ? data.length : 0;
        if (length > 0) {
            pagination.totalItems = data[0]["totalItems"];
            pagination.totalPages = Math.ceil(pagination.totalItems /100);
            pagination.currentItems = ((Math.abs(pagination.totalItems) % pagination.pageSize) === length
                ? pagination.totalItems
                : length > 0
                    ? length * (status ? pagination.pageIndex + 1 : pagination.pageIndex)
                    : 0);
            pagination.currentPage = status ? pagination.pageIndex + 1 : pagination.pageIndex;
        }
    }

    static random(length: number) {
        let result = "";
        const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        const charactersLength = characters.length;
        for (let i = 0; i < length; i++) {
            result += characters.charAt(Math.floor(Math.random() * charactersLength));
        }
        return result;
    }

    static defaultErrorMessage() {
        return "Sorry error occurred. Please try again later.";
    }

    static handleError(error: HttpErrorResponse) {
        try {
            if (error.error === undefined || error.error === null || error.error === "" || error.error.type === "error") {
                return "";
            }

            return error.error;
        } catch (e) {
            return "";
        }
    }

    static prepareFormData(model: object) {
        const formData = new FormData();
        const keys = Object.keys(model);
        keys.forEach((key) => {
            formData.append(key, model[key]);
        });

        return formData;
    }

    static isInvalidFileType(contentType: string) {
        // const docTypes = ["application/doc", "application/ms-doc", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"];
        // const excelTypes = ["application/excel", "application/vnd.ms-excel", "application/x-excel", "application/x-msexcel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"];
        const pdfTypes = ["application/pdf"];
        // const odtTypes = ["application/odt"];
        // const rtfTypes = ["application/rtf"];
        // const txtTypes = ["text/plain"];
        const jpgTypes = ["image/jpeg", "image/pjpeg"];
        const pngTypes = ["image/png"];
        const gifTypes = ["image/gif"];

        if ([...pdfTypes, ...jpgTypes, ...pngTypes, ...gifTypes].indexOf(contentType) > -1) {
            return false;
        }

        return true;
    }

    static isInvalidImageType(contentType: string) {
        const jpgTypes = ["image/jpeg", "image/pjpeg"];
        const pngTypes = ["image/png"];
        const gifTypes = ["image/gif"];

        if ([...jpgTypes, ...pngTypes, ...gifTypes].indexOf(contentType) > -1) {
            return false;
        }

        return true;
    }

    static isInvalidFileSize(size: number) {
        return Math.round((size / 1024)) > 10240;
    }

    static async readFile(file: File): Promise<string | ArrayBuffer> {
        return new Promise<string | ArrayBuffer>((resolve, reject) => {
            const reader = new FileReader();

            reader.onload = (e) => {
                return resolve((e.target as FileReader).result);
            };

            reader.onerror = () => {
                return reject(null);
            };

            if (!file) {
                return reject(null);
            }

            reader.readAsDataURL(file);
        });
    }

    static getHtml(url, callback) {
        if (!XMLHttpRequest) {
            callback("");
        }

        const request = new XMLHttpRequest();
        request.onload = () => {
            if (callback && typeof (callback) === "function") {
                callback(request.responseXML);
            }
        }

        request.open("GET", url);
        request.responseType = "document";
        request.send();
    }

    static addOrRemoveLogoStyle = (type: boolean, callback: Function = () => { }) => {
        if (!type) {
            UtilHelper.addWithOutLogoStyleFile(() => {
                callback();
            })
        } else {
            UtilHelper.removeWithOutLogoStyleFile(() => {
                callback();
            })
        }
    }
    
    static fullCalendarStyleSheets = ["fullcalendar/core.css", "fullcalendar/daygrid.css", "fullcalendar/list.css", "fullcalendar/timegrid.css", "calendar.css"];

    static addFullCalendarCss(callBack: Function) {
        const head = document.getElementsByTagName('head')[0];
        this.fullCalendarStyleSheets.forEach((item) => {
            const fileref = document.createElement("link")
            fileref.setAttribute("rel", "stylesheet")
            fileref.setAttribute("type", "text/css")
            const fileName = location.origin + location.pathname + `assets/css/styles/${item}`;
            fileref.setAttribute("href", fileName);
            fileref.media = 'all';
            head.appendChild(fileref);
        });
        setTimeout(() => {
            callBack();
        });
    }

    static removeFullCalendarCss(callBack: Function) {
        this.fullCalendarStyleSheets.forEach((item) => {
            const fileName = location.origin + location.pathname + `assets/css/styles/${item}`;
            $(`link[href="${fileName}"]`).remove();
        });
        setTimeout(() => {
            callBack();
        });
    }

    static addWithOutLogoStyleFile = (callback: Function = () => { }) => {
        const head = document.getElementsByTagName('head')[0];
        const fileref = document.createElement("link")
        fileref.setAttribute("rel", "stylesheet")
        fileref.setAttribute("type", "text/css")
        const fileName = location.origin + location.pathname + "assets/css/without-logo.css";
        fileref.setAttribute("href", fileName);
        fileref.media = 'all';
        head.appendChild(fileref);
        setTimeout(() => {
            callback();
        });
    }

    static removeWithOutLogoStyleFile = (callback: Function = () => { }) => {
        const fileName = location.origin + location.pathname + "assets/css/without-logo.css";
        $(`link[href="${fileName}"]`).remove();
        setTimeout(() => {
            callback();
        });
    }

    static isEmpty = (values: any) => {
        if (values !== undefined)
            if (values !== null) {
                if (values !== "") {
                    return true;
                } else {
                    return false;
                }
            } else
                return false;
        else {
            return false;
        }
    }
}