var NProgress = require("../vendors/nprogress.js")
export class ApiService {
    _entityName = "";
    _actionList = [];

    constructor(model, entityName) {
        this._entityName = entityName;
        this._actionList = model.actionList;
        this._self = this;
    }

    static createHeader(verb, data) {
        var token = _h.getTvm();
        if (token === null)
            _h.backToLogin();
        var header = {};
        if (data && typeof data === 'object') {
            header['Content-Type'] = 'application/json';
        }
        header['dmo_cur_ucp'] = token;

        header['__RequestVerificationToken'] = document.getElementsByName("__RequestVerificationToken")[0].value;


        return header;
    }

    static prepareData(data, verb) {
        if (!data)
            return "";
        if (typeof data !== 'object')
            return data;
        if (verb === "POST")
            return JSON.stringify(data);
        return data;
    }

    static getActionVerb(name) {
        name = name.toLowerCase();
        if (name.indexOf("filterby") !== -1 || name.indexOf("get") !== -1)
            return "GET";
        else if (name.indexOf("post") !== -1
            || name.indexOf("put") !== -1
            || name.indexOf("delete") !== -1)
            return "POST";
    }

    static appendQueryString(url, data) {
        if (data) {
            url += '?';
            for (let key in data) {
                if (Object.prototype.hasOwnProperty.call(data, key)) {
                    if (!_h.isEmpty(data[key])) {
                        if (Array.isArray(data[key])) {
                            if (data[key].length > 0) {
                                var arrStr = "";
                                for (var i = 0; i < data[key].length; i++) {
                                    arrStr += `${key}[${i}]=${data[key][i]}&`;
                                }
                                url += arrStr;
                            }
                        } else
                            url += `${key}=${data[key]}&`;
                    }
                }
            }
        }
        if (url.endsWith("&"))
            url = url.substring(0, url.length - 1);
        return url;
    }

    createApiAddress(name) {
        name = name.toLowerCase();
        if (name.indexOf("/api") !== -1)
            return name;
        if (this._actionList.indexOf(name) !== -1) {
            return `/api/${this._entityName.toLowerCase()}/${name}`;
        }
        if (commonActionList.indexOf(name) !== -1) {
            return `/api/common/${name}`;
        }
    }

    static handleResponseHeaders(response) {
        if (!response || !response.headers)
            return;
        var process = response.headers.get('Process');
        if (process !== null && process !== undefined) {
            _h.kocnx().checkProcessQueue(true, window.firstload);
            window.firstload = false;
        }
        var serverDate = response.headers.get('ServerDate');
        if (serverDate !== null && serverDate !== undefined) {
            localStorage.setItem("ServerDate", serverDate);
        }
    }

    request(model) {
        var rId;
        var verb = ApiService.getActionVerb(model.name);
        var url = this.createApiAddress(model.name);
        var dataModel = ApiService.prepareData(model.data, verb);
        var headers = ApiService.createHeader(verb, model.data);
        var options = {
            method: verb,
            headers: headers
        }
        switch (verb) {
            case "POST":
                options.body = dataModel;
                break;
            case "GET":
                url = ApiService.appendQueryString(url, model.data);
                break;
        }
        if (!model.splashId) {
            ApiService.startLoader();
        } else {
            rId = ApiService.startSplash(model.splashId);
        }


        fetch(url, options)
            .then(response => {
                if (!model.splashId) {
                    ApiService.stopLoader();
                } else {
                    ApiService.stopSplash(rId);
                }
                ApiService.handleResponseHeaders(response);
                try {
                    switch (response.status) {
                        case 200:
                            try {
                                response.text().then(res => {
                                    var data = res === "" ? {} : JSON.parse(res);
                                    if (!_h.isNullOrEmpty(data)) {
                                        if (!_h.isNullOrEmpty(data.tvm)) {
                                            _h.kocnx().changeTvm(data.tvm, true);
                                        }
                                        if (!_h.isNullOrEmpty(data.aft)) {
                                            _h.changeAft(data.aft);
                                        }
                                        if (_h.any(data.warnings)) {
                                            _h.warningListHandler(data.warnings);
                                        }
                                        if (_h.any(data.errors)) {
                                            _h.errorListHandler(data.errors);
                                        } else {
                                            model.success(data);
                                        }
                                    }
                                });
                            } catch (e) {
                                return "";
                            }
                            break;
                        default:
                            ApiService.handleError(response.status, model, verb);
                            break;
                    }
                } catch (e) {
                    var data = {};
                    if (!_h.isNullOrEmpty(data)) {
                        if (_h.any(data.warnings)) {
                            _h.warningListHandler(data.warnings);
                        }
                        if (_h.any(data.errors)) {
                            _h.errorListHandler(data.errors);
                        } else {
                            model.success(data);
                        }
                    }
                }
            });
    }

    static request(model) {
        var rId;
        var url = model.url;
        if (model.url.indexOf("/api") === -1)
            url = `/api/common/${model.url}`;
        if (model.url.indexOf("/account") !== -1)
            url = model.url;
        var verb = model.verb ? model.verb : ApiService.getActionVerb(url);
        var headers = ApiService.createHeader(verb, model.data);
        if (!model.notShowAjaxLoader) {
            if (!model.splashId) {
                ApiService.startLoader();
            } else {
                rId = ApiService.startSplash(model.splashId);
            }
        }
        var options = {
            method: verb,
            headers: headers
        };
        var dataModel = ApiService.prepareData(model.data, verb);
        switch (verb) {
            case "POST":
                options.body = dataModel;
                break;
            case "GET":
                url = ApiService.appendQueryString(url, model.data);
                break;
        }

        fetch(url, options)
            .then(response => {
                if (!model.splashId) {
                    ApiService.stopLoader();
                } else {
                    ApiService.stopSplash(rId);
                }
                ApiService.handleResponseHeaders(response);
                switch (response.status) {
                    case 200:
                        try {
                            response.text().then(res => {
                                var data = res === "" ? {} : JSON.parse(res);
                                if (!_h.isNullOrEmpty(data)) {
                                    if (!_h.isNullOrEmpty(data.tvm)) {
                                        _h.kocnx().changeTvm(data.tvm, true);
                                    }
                                    if (!_h.isNullOrEmpty(data.aft)) {
                                        _h.changeAft(data.aft);
                                    }
                                    if (_h.any(data.warnings)) {
                                        _h.warningListHandler(data.warnings);
                                    }
                                    if (_h.any(data.errors)) {
                                        _h.errorListHandler(data.errors);
                                        if (model["concurrencyHandler"])
                                            model.concurrencyHandler(data);
                                    } else {
                                        model.success(data);
                                    }
                                }
                            });
                        } catch (e) {
                            var data = {};
                            if (!_h.isNullOrEmpty(data)) {
                                if (_h.any(data.warnings)) {
                                    _h.warningListHandler(data.warnings);
                                }
                                if (_h.any(data.errors)) {
                                    _h.errorListHandler(data.errors);
                                } else {
                                    model.success(data);
                                }
                            }
                        }
                        break;
                    default:
                        if (model.url.indexOf("newtoken") !== -1) {
                            model.error(response.status);
                        } else {
                            ApiService.handleError(response.status, model, verb);
                        }
                        break;
                }
            });
    }

    static handleError(status, model, verb) {
        var context = _h.kocnx();
        switch (status) {
            case 500:
                var text = _h.getApiMessage("ErrorUnknownServer");
                _h.failToast(text);
                break;
            case 550:
                context.openLoginModal();
                if (model["error"])
                    model.error(status);
                break;
            case 551:
                _h.failToast("دسترسی شما به این بخش محدود شده است");
                break;
            case 554:
                _h.failToast("حساب کاربری شما غیر فعال شده است");
                setTimeout(function () {
                    _h.backToLogin();
                },
                    2000);
                break;
            case 553:
            case 558:
            case 574:
                _h.backToLogin();
                break;
            case 561:
                var text = _h.getApiMessage("UserHasNoAccessInSystem");
                _h.failToast(text);
                setTimeout(function () {
                    _h.backToLogin();
                },
                    2000);
                break;
            case 562:
                context.openLoginModal();
                break;
            case 571:
                var text = _h.getApiMessage("CompanyIsNotActive");
                _h.failToast(text);
                setTimeout(function () {
                    context.refreshToken();
                }, 2000);
                break;
            case 572:
                var periodIsClosed = _h.getApiMessage("PeriodIsClosed");
                _h.failToast(periodIsClosed);
                break;
            case 573:
                var periodIsDisabled = _h.getApiMessage("PeriodIsDisabled");
                _h.failToast(periodIsDisabled);
                break;
            case 591:
                context.refreshToken();
                break;
            case 592:
                var noEnabledPeriod = _h.getApiMessage("NoEnabledPeriod");
                _h.failToast(noEnabledPeriod);
                setTimeout(function () {
                    window.location.href = "/basicinfo";
                },
                    2000);
                break;
            case 600:
                var insufficientInfo = _h.getApiMessage("InsufficientInformations");
                _h.failToast(insufficientInfo);
                break;
            case 601:
                var fingerPrintMismatch = _h.getApiMessage("FingerPrintMismatch");
                _h.failToast(fingerPrintMismatch);
                break;
            case 602:
                var limitedCpuOrMemory = _h.getApiMessage("LimitedCpuOrMemory");
                _h.failToast(limitedCpuOrMemory);
                break;
            case 610:
                _h.toggleDisableSections(true);
                break;
            case 611:
                var consolidationInProgress = _h.getApiMessage("ConsolidationInProgress");
                _h.failToast(consolidationInProgress);
                break;
            case 612:
                var fileUploadTimeError = _h.getApiMessage("FileUploadTimeError");
                _h.failToast(fileUploadTimeError);
                break;

            default:
                if (!model["error"] && !model.messageType) {
                    if (model.messageType)
                        toast.error(this._entityName, model.messageType, model.messageKey);
                    else
                        toast.error(this._entityName, verb.toLowerCase(), model.messageKey);
                }
                if (model["error"])
                    model.error();
                break;
        }
    }

    static startLoader() {
        NProgress.configure({ parent: "#np-bar", showSpinner: false });
        NProgress.start();
    }

    static stopLoader() {
        NProgress.done();
    }

    static startSplash(e) {
        var randomId = Number((Math.random() * (10000000 - 100) + 100).toString().replace(".", ""));
        var tag = '<div class="splash" style="opacity: .9;position: absolute;" id="bd-' + randomId + '">' +
            '<div class="splash-title" style="position: absolute;top: 55%;left: 44%;margin:0;">' +
            '<div class="spinner">' +
            '<div class="rect1"></div>' +
            '<div class="rect2"></div>' +
            '<div class="rect3"></div>' +
            '<div class="rect4"></div>' +
            '<div class="rect5"></div>' +
            '</div></div></div>';
        if (typeof e === "string") {
            var target = $(e);
            if (target.length) {
                target.prepend(tag);
            }
        } else {
            var targetFooterModal = $(e.target).closest(".modal-footer");
            if (targetFooterModal.length) {
                targetFooterModal.prepend(tag);
            }
        }
        return randomId;
    }

    static stopSplash(randomId) {
        var targetBody = $("#bd-" + randomId);
        if (targetBody.length) {
            targetBody.remove();
        } else {
            var splashes = $(".splash");
            if (splashes.length)
                for (var i = 0; i < splashes.length; i++) {
                    var target = splashes[i];
                    $(target).remove();
                }
        }
    }

    static isOnline() {
        var nav = window.navigator;
        var isInline = nav.onLine;
    }

}

var commonActionList = ["gettableinfo", "putfolders", "getconsolidationbranch", "postisunique", "getformulatooltip",
    "postsearchprofile", "deletesearchprofile", "postsetting", "gettablelist", "getcompanyownership", "putstatetype",
    "getlastpriority", "getmappingtreelist", "getnodeselection", "putpriority", "getgeneraltreelist", "getxbrlconcepts"];