require('knockout.validation');
require('../../vendors/bootstrap');
require('../../vendors/knockout.validation.fa-IR');
const toastr = require('../../vendors/toastr');

const apiStatusResource = {
    InvalidUserOrPasswordError: {
        fa: 'نام کاربری و یا رمز عبور صحیح نیست',
    },
    ErrorLoginLockout: {
        fa: 'حساب کاربری شما غیر فعال است',
    },
    UserHasNoAccessInSystem: {
        fa: 'این حساب کاربری مجوز ورود به هیچ یک از شرکتهای تعریف شده در سیستم را ندارد',

    },
    ErrorLoginNotAuthorized: {
        fa: 'شما مجاز به ورود به حساب گروه یا شرکت انتخاب شده نمی باشید',
    },
    CompanyIsNotActive: {
        fa: 'حساب کاربری این شرکت غیرفعال می باشد',
    },
    ErrorUnknownServer: {
        fa: 'در هنگام ارتباط با سرور خطای ناشناخته ای رخ داده است',
    },
    UserIsLocked: {
        fa: 'حساب کاربری شما به دلیل ورود بیش از حد مجاز رمز اشتباه  مسدود شده است. برای فعالسازی مجدد آن به مدیر سیستم مراجعه کنید.',
    },
    PasswordExpired: {
        fa: 'رمز عبور شما منقضی شده است.لطفا رمز عبور جدیدی را وارد کنید',
    },
    CaptchaInValid: {
        fa: 'مقدار وارد شده برای تصویر امنیتی صحیح نیست',
    },
    CaptchaTimeOut: {
        fa: 'مهلت وارد کردن تصویر امنیتی به پایان رسیده است. لطفا تصویر امنیتی را رفرش کنید',
    },
    OtpSuccess: {
        fa: 'رمز عبور موقت به ایمیل ثبت شده در پروفایل کاربر ارسال خواهد شد',
    },
    OTPFillInput: {
        fa: 'لطفا نام کاربری و مقدار کپچا را وارد کنید',
    },
    OTPExpired: {
        fa: 'رمز یکبار مصرف شما منقضی شده است . لطفا رمز جدیدی دریافت نمایید',
    },
    UserMustLoginWithSSO: {
        fa: 'این حساب کاربری تنها مجاز به ورود از طریق سیستم متمرکز می باشد',
    },
    SSoUserUnauthorized: {
        fa: 'احرازهویت کاربر در سامانه متمرکز انجام نشد',
    },
    SSOUserNameIsAlreadyExist: {
        fa: 'نام کاربری مورد نظر قبلا در سامانه ثبت شده است',
    },
};

const helper = function (options) {
    const failToast = function (message) {
        toastr.options = {
            "newestOnTop": false,
            "positionClass": "toast-top-left",
            "closeButton": false,
            "toastClass": "animated fadeInDown"
        };
        toastr.options.rtl = true;
        toastr.error(message);
    };
    const successToast = function (message) {
        toastr.options = {
            "newestOnTop": false,
            "positionClass": "toast-bottom-left",
            "closeButton": false,
            "toastClass": "animated fadeInDown"
        };
        toastr.options.rtl = true;
        toastr.success(message);
    }
    const getApiMessage = function (key) {
        const item = apiStatusResource[key];
        return item["fa"] || item['default'] || "";
    };
    const hasSpecialChar = function (str) {
        if (!str)
            return false;
        var res = false;
        for (var i = 0; i < str.length; i++) {
            if (/^[!@#\$%\^\&*\)\(+=._-]+$/g.test(str[i]))
                res = true;
        }
        return res;
    };
    const stringIsEnglish = function (str) {
        var index;
        var english = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@#$%^&*()_+-.<>?|\\/";
        for (index = str.length - 1; index >= 0; --index) {
            if (english.indexOf(str.substring(index, index + 1)) < 0) {
                return false;
            }
        }
        return true;
    };
    const countBackNumberZero = function (str) {
        var count = 0;
        for (var i = 0; i < str.length; i++) {
            var target = str.substring(i, i + 1);
            if (target === "0")
                count++;
            else {
                return count;
            }
        }
        return count;
    };
    return {
        getApiMessage: getApiMessage,
        stringIsEnglish: stringIsEnglish,
        hasSpecialChar: hasSpecialChar,
        countBackNumberZero: countBackNumberZero,
        failToast: failToast,
        successToast: successToast,
    }
}();

ko.bindingHandlers.valueWithInit = {
    init: function (element, valueAccessor, allBindingsAccessor, context) {
        const observable = valueAccessor();
        const value = element.value;
        observable(value);
        ko.bindingHandlers.value.init(element, valueAccessor, allBindingsAccessor, context);
    },
    update: ko.bindingHandlers.value.update
};
ko.validation.rules['englishOnly'] = {
    validator: function (val, otherVal) {
        if (val === null || val === undefined)
            return true;
        return helper.stringIsEnglish(val);
    },
    message: 'لطفا به زبان انگلیسی وارد کنید'
};
ko.validation.rules['confirmPassword'] = {
    getValue: function (o) {

        return (typeof o === 'function' ? o() : o);
    },
    validator: function (val, otherField) {
        var value2 = this.getValue(otherField.params);
        if (value2 === val)
            return true;
        else
            return false;
    },
    message: 'مقدار رمز عبور و تایید باید یکسان باشد'
};
ko.validation.rules['passwordComplexity'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (val, otherField) {
        //var res = /(?=^[^\s]{8,20}$)((?=.*?\d)(?=.*?[A-Z])(?=.*?[a-z])|(?=.*?\d)(?=.*?[^\w\d\s])(?=.*?[a-z])|(?=.*?[^\w\d\s])(?=.*?[A-Z])(?=.*?[a-z])|(?=.*?\d)(?=.*?[A-Z])(?=.*?[^\w\d\s]))^.*/.test('' + val + '');

        var arr = this.getValue(otherField);
        var rx = /(?=^[^\s]{4,20}$)((?=.*?\d)(?=.*?[A-Z])(?=.*?[a-z])|(?=.*?\d)(?=.*?[^\w\d\s])(?=.*?[a-z])|(?=.*?[^\w\d\s])(?=.*?[A-Z])(?=.*?[a-z])|(?=.*?\d)(?=.*?[A-Z])(?=.*?[^\w\d\s]))^.*/;
        return helper.hasSpecialChar(val) && rx.test('' + val) && val.length >= arr[0];
    },
    message: function (params, observable, hg) {
        var min = params[0];
        return `رمز عبور باید حداقل  ${min} کاراکتر ، حداکثر 20 کاراکتر و شامل حروف، اعداد و کارکترهای ویژه باشد`;
    }
};

ko.validation.rules['numberOnly'] = {
    validator: function (val, otherVal) {
        if (val !== null && val !== undefined && val !== "") {
            var test = val.toString();
            var a = parseInt(test);
            var afterParse = a.toString();
            if (afterParse.length <= 0)
                return false;
            if (afterParse.length === test.length)
                return true;
            else {
                var backZero = helper.countBackNumberZero(test);
                if (test.length - (afterParse.length + backZero) === 0) {
                    return true;
                } else {
                    return false;
                }
            }
        }
        return true;
    },
    message: ' فقط ورود اعداد مجاز است'
};
function ChangePassword() {
    const self = this;
    self.userName = ko.observable();
    self.newPassword = ko.observable();
    self.confirmPassword = ko.observable();
    self.setValidationObject = function (complexity) {
        var l = $(".login-box").attr("data-pmc");
        const obj = {};
        obj.newPassword = self.newPassword.extend({
            required: true,
            englishOnly: true,
            passwordComplexity: [l]
        });
        obj.confirmPassword = self.confirmPassword.extend({
            required: true,
            confirmPassword: { params: self.newPassword }
        });
        self.validationObject = ko.validatedObservable(obj);
    }
}
function Login() {
    const self = this;
    self.userName = ko.observable();
    self.password = ko.observable();
    self.otpCode = ko.observable();
    self.captchaStr = ko.observable();
    self.captchaError = ko.observable(null);
    self.captchaStr.subscribe(function (newValue) {
        if (newValue !== null) {
            if (self.captchaError() !== null)
                self.captchaError(null);
        }
    });
    self.setValidationObject = function (complexity, showCaptcha, otp) {
        const obj = {};
        var l = $(".login-box").attr("data-pmc");
        obj.userName = self.userName.extend({
            required: true,
            englishOnly: true,
            minLength: 4,
            maxlength: 20
        });
        if (!otp) {
            if (complexity)
                obj.password = self.password.extend({
                    required: true,
                    englishOnly: true
                });
            else
                obj.password = self.password.extend({
                    required: true,
                    englishOnly: true,
                    minLength: Number(l),
                    maxlength: 20
                });
        } else {
            obj.otpCode = self.otpCode.extend({
                required: true,
                numberOnly: true,
                minLength: 5,
                maxlength: 7
            });
        }

        if (showCaptcha)
            obj.captchaStr = self.captchaStr.extend({ required: true });

        self.validationObject = ko.validatedObservable(obj);
    }
    self.refreshValidationMessages = function () {
        self.userName.valueHasMutated();
        self.password.valueHasMutated();
    }
}
function LoginViewModel() {
    const self = this;
    self.forceChangePassword = ko.observable(false);
    self.isPasswordComplexity = ko.observable(true);
    self.showCaptcha = ko.observable(false);
    self.showOneTimePassword = ko.observable(false);
    self.codeSend = ko.observable(false);
    self.loginModel = ko.observable();
    self.changePasswordModel = ko.observable();
    self.getCaptcha = function () {
        self.loginModel().captchaStr(null);

        var root = location.protocol + '//' + location.host;
        const img = document.getElementById("Captcha_Image");
        img.src = root + '/account/getcaptcha' + "?t=" + new Date().getTime();
    }
    self.login = function (item) {
        if (!item.validationObject.isValid()) {
            item.validationObject.errors.showAllMessages();
            return false;
        }
        let model = {
            userName: item.userName(),
            password: item.password(),
            captcha: item.captchaStr(),
            otp: self.showOneTimePassword(),
        };
        if (self.showOneTimePassword()) {
            model.password = item.otpCode();
        }

        var headers = self.getHeaders();
        $.ajaxSetup({ cache: false });
        $.ajax({
            url: '/account/posttoken',
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            type: "POST",
            headers: headers,
            data: JSON.stringify(model),
            success: function (data, textStatus, request) {
                if (data) {
                    $('.splash').css('display', 'block');
                    self.handleDataToken(data);
                    window.location.href = "/basicinfo";
                }
            },
            error: function (data) {
                data = data.status;
                self.handleErrors(data, item);
            }
        });
    }
    self.handleErrors = function (data, item) {
        let text, model;
        switch (data) {
            case 552:
                text = helper.getApiMessage("InvalidUserOrPasswordError");
                helper.failToast(text);
                self.getCaptcha();
                if (!self.showOneTimePassword()) {
                    self.loginModel().setValidationObject(self.isPasswordComplexity(), true, false);
                }
                break;
            case 553:
                self.SSOActive(false);
                self.forceChangePassword(true);
                model = new ChangePassword();
                model.userName(item.userName());
                self.changePasswordModel(model);
                self.changePasswordModel().setValidationObject(true);
                break;
            case 558:
                self.forceChangePassword(true);
                model = new ChangePassword();
                model.userName(item.userName());
                self.changePasswordModel(model);
                text = helper.getApiMessage("PasswordExpired");
                helper.failToast(text);
                self.changePasswordModel().setValidationObject(true);
                break;
            case 554:
                text = helper.getApiMessage("ErrorLoginLockout");
                helper.failToast(text);
                break;
            case 556:
                text = helper.getApiMessage("ErrorLoginNotAuthorized");
                helper.failToast(text);
                break;
            case 557:
                text = helper.getApiMessage("UserIsLocked");
                helper.failToast(text);
                break;
            case 559:
                text = helper.getApiMessage("CaptchaInValid");
                self.loginModel().captchaError(text);
                self.getCaptcha();
                break;
            case 560:
                text = helper.getApiMessage("CaptchaTimeOut");
                self.loginModel().captchaError(text);
                self.getCaptcha();
                break;
            case 561:
                text = helper.getApiMessage("UserHasNoAccessInSystem");
                helper.failToast(text);
                break;
            case 571:
                text = helper.getApiMessage("CompanyIsNotActive");
                helper.failToast(text);
                break;
            case 564:
                text = helper.getApiMessage("OTPExpired");
                helper.failToast(text);
                break;
            case 580:
                text = helper.getApiMessage("SSoUserUnauthorized");
                helper.failToast(text);
                break;
            case 582:
                text = helper.getApiMessage("UserMustLoginWithSSO");
                helper.failToast(text);
                break;
            case 583:
                text = helper.getApiMessage("SSOUserNameIsAlreadyExist");
                helper.failToast(text);
                break;
            default:
                text = helper.getApiMessage("ErrorUnknownServer");
                helper.failToast(text);
                break;
        }
    }
    self.changePassword = function (item) {
        if (!item.validationObject.isValid()) {
            item.validationObject.errors.showAllMessages();
            return false;
        }
        const returnurl = $(".return-url").text();
        const model = {
            userName: item.userName(),
            newPassword: item.newPassword(),
            confirmPassword: item.confirmPassword()
        };
        $.ajaxSetup({ cache: false });
        $.ajax({
            url: '/api/account/forcechangepassword',
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            type: "POST",
            data: JSON.stringify(model),
            success: function (data, textStatus, request) {
                if (data) {
                    $('.splash').css('display', 'block');
                    self.handleDataToken(data);
                    if (returnurl === "/" || returnurl === "")
                        window.location.href = "/basicinfo";
                    else
                        window.location.href = returnurl;

                }
            },
            error: function (data) {
                data = data.status;
                self.handleErrors(data, item);
            }
        });
    }
    self.clearLocalStorage = function () {
        localStorage.removeItem("sts");
        localStorage.removeItem("lsl");
        localStorage.removeItem("ud");
        localStorage.removeItem("sd");
        localStorage.removeItem("fs");
    }
    self.getHeaders = function () {
        return {
            "__RequestVerificationToken": document.getElementsByName("__RequestVerificationToken")[0].value
        };
    }
    self.getOtp = function () {
        if (!self.loginModel().captchaStr() || !self.loginModel().userName()) {
            text = helper.getApiMessage("OTPFillInput");
            helper.failToast(text);
            return false;
        }


        let model = {
            userName: self.loginModel().userName(),
            captcha: self.loginModel().captchaStr(),
            otp: true
        };
        var headers = self.getHeaders();
        $.ajaxSetup({ cache: false });
        $.ajax({
            url: '/account/postotp',
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            type: "POST",
            headers: headers,
            data: JSON.stringify(model),
            success: function (data, textStatus, request) {
                self.codeSend(true);
                var text = helper.getApiMessage("OtpSuccess");
                helper.successToast(text);
                self.getCaptcha();
            },
            error: function (data) {
                data = data.status;
                let text, model;
                switch (data) {
                    case 559:
                        text = helper.getApiMessage("CaptchaInValid");
                        self.loginModel().captchaError(text);
                        self.getCaptcha();
                        break;
                    case 560:
                        text = helper.getApiMessage("CaptchaTimeOut");
                        self.loginModel().captchaError(text);
                        self.getCaptcha();
                        break;
                    default:
                        text = helper.getApiMessage("ErrorUnknownServer");
                        helper.failToast(text);
                        break;
                }
            }
        });
    }
    self.init = function () {
        var tt = $(".login-box").attr("data-tt");
        var co = $(".login-box").attr("data-co");
        if (co) {
            self.handleErrors(Number(co));
        } else {
            if (tt) {
                self.tt(tt);
                self.SSOActive(true);
                self.getSSO();
                return;
            }
        }
        self.clearLocalStorage();
        self.showOneTimePassword(false);
        self.setLoginType();
    }
    self.setLoginType = function () {
        self.loginModel(new Login());
        if (self.showOneTimePassword()) {
            self.showCaptcha(true);
            self.getCaptcha();
            self.loginModel().setValidationObject(self.isPasswordComplexity(), true, true);

        } else {
            var res = $(".login-box").attr("data-tag") === "True";
            if (res) {
                self.showCaptcha(true);
                self.getCaptcha();
                self.loginModel().setValidationObject(self.isPasswordComplexity(), true, false);
            } else {
                self.showCaptcha(false);
                self.loginModel().setValidationObject(self.isPasswordComplexity(), false, false);
            }
        }
        setTimeout(function () {
            self.loginModel().refreshValidationMessages();
            $(".temp-control").remove();
        }, 100);
    }
    self.changeLoginType = function () {
        self.showOneTimePassword(!self.showOneTimePassword());
        self.setLoginType();
    }
    self.tt = ko.observable();
    self.SSOActive = ko.observable(false);
    self.backToLogin = function () {
        self.tt("");
        self.SSOActive(false);
        self.showOneTimePassword(false);
        self.setLoginType();
    }
    self.checkSSOLoginStatus = function () {
        self.getSSO();
    }
    self.handleDataToken = function (data) {
        if (data) {
            var lh = $(".login-box").attr("data-lh");
            if (lh == "True") {
                localStorage.setItem("fs", "true");
            }            
            localStorage.setItem("lsl", data.lsl);
            localStorage.setItem("ud", JSON.stringify(data.ud));
            localStorage.setItem("sd", JSON.stringify(data.sd));
            if (data.sts.length > 0)
                localStorage.setItem("sts", JSON.stringify(data.sts));
            else {
                localStorage.setItem("sts", JSON.stringify([]));
            }
        }
    }
    self.getSSO = function () {
        let model = {
            tt: self.tt()
        };
        var headers = self.getHeaders();
        $.ajaxSetup({ cache: false });
        $.ajax({
            url: '/account/postssotoken',
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            type: "POST",
            headers: headers,
            data: JSON.stringify(model),
            success: function (data, textStatus, request) {
                if (data) {
                    switch (data.status) {
                        case 1:
                            self.SSOActive(true);
                            break;
                        case 2:
                            self.handleErrors(data.errorCode);
                            break;
                        case 3:
                            $('.splash').css('display', 'block');
                            self.handleDataToken(data.tvm);
                            window.location.href = "/basicinfo";
                            break;
                        case 4:
                            self.SSOActive(false);
                            self.forceChangePassword(true);
                            model = new ChangePassword();
                            model.userName(data.userName);
                            self.changePasswordModel(model);
                            self.changePasswordModel().setValidationObject(true);
                            break;
                    }
                }
            },
            error: function (data) {
            }
        });
    }
}
ko.validation.locale('fa-IR');
ko.validation.init({
    grouping: {
        deep: true,
        live: true,
        observable: true
    }
});
const vm = new LoginViewModel();
ko.applyBindings(vm, document.getElementById("login-page"));
vm.init();