require('knockout.validation');
import { ApiService } from "./apiService.js";

function stringIsEnglish(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;
}
function IsUserNameValid(str) {
    var index;
    str = str.replace(/\u200C/g, ' ').replace(/\&zwnj;/g, ' ');
    var english = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.";
    for (index = str.length - 1; index >= 0; --index) {
        if (english.indexOf(str.substring(index, index + 1)) < 0) {
            return false;
        }
    }
    return true;
}
function isValidIP(ipAddress) {
    var maskbit = 0;
    if (ipAddress.indexOf("/") !== -1) {
        var index = ipAddress.indexOf("/");
        var maskPart = ipAddress.substring(index);
        maskbit = parseInt(maskPart.replace("/", ""));
        ipAddress = ipAddress.replace(maskPart, "");
        if (isNaN(maskbit)) return false;

        if (maskbit < 0 || maskbit > 32) return false;
    }
    const ipParts = ipAddress.split('.');

    if (ipParts.length !== 4) return false;

    for (let i = 0; i < 4; i++) {
        const ipPart = parseInt(ipParts[i]);
        if (isNaN(ipPart)) return false;
        if (ipPart < 0 || ipPart > 255) return false;
    }
    return true;
}
ko.validation.rules['IsValidIpAddress'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (val) {
        var value = this.getValue(val);
        if (!value)
            return false;
        var res = isValidIP(value);
        return res;
    },
    message: function (params, observable, hg) {
        return 'فرمت آدرس IP صحیح نیست';
    }
};
ko.validation.rules['checkImage'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (file, otherField, callback) {
        if (file === undefined || file === null)
            return true;
        var ext = _h.getExtension(otherField.params[0]());
        if ((file.indexOf("png") !== -1
            || file.indexOf("jpg") !== -1
            || file.indexOf("jpeg") !== -1) && (ext.indexOf("png") !== -1
            || ext.indexOf("jpg") !== -1
            || ext.indexOf("jpeg") !== -1))
            return true;
        return false;
    },
    message: 'تصویر لوگو باید حداکثر 120 پیکسل و با یکی از فرمت های "png", "jpg" باشد'
};
ko.validation.rules['checkExcel'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (file, otherField, callback) {
        if (file === undefined || file === null)
            return true;
        var ext = _h.getExtension(otherField.params[0]());
        if ((file.indexOf("officedocument") !== -1 || file.indexOf("ms-excel") !== -1) &&
        (ext.indexOf("csv") !== -1 || ext.indexOf("xls") !== -1 || ext.indexOf("xlsx") !== -1))
            return true;
        return false;
    },
    message: 'فقط بارگزاری فایل با فرمت های "csv", "xls", "xlsx" امکان پذیر است'
};
ko.validation.rules['checkOnlyExcel'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (file, otherField, callback) {
        if (file === undefined || file === null)
            return true;
        var ext = _h.getExtension(otherField.params[0]());
        if ((file.indexOf("officedocument") !== -1 || file.indexOf("ms-excel") !== -1) &&
            (ext.indexOf("xls") !== -1 || ext.indexOf("xlsx") !== -1))
            return true;
        return false;
    },
    message: 'فقط بارگزاری فایل با فرمت های "csv", "xls", "xlsx" امکان پذیر است'
};
ko.validation.rules['checkBackupFile'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (file, otherField, callback) {
        if (file === undefined || file === null)
            return true;
        var value = this.getValue(otherField.params);
        if (value === null || value === undefined)
            value = 0;
        var ext = _h.getExtension(value);
        if (ext.indexOf("dbuf") !== -1)
            return true;
        return false;
    },
    message: 'فقط بارگذاری فایل با فرمت  "dbuf" امکان پذیر است'
};
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 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 _h.hasSpecialChar(val) && rx.test('' + val) && val.length >= arr[0];
    },
    message: function (params, observable, hg) {
        var min = params[0];
        return `رمز عبور باید حداقل  ${min} کاراکتر ، حداکثر 20 کاراکتر و شامل حروف، اعداد و کارکترهای ویژه باشد`;
    }
};
ko.validation.rules['englishOnly'] = {
    validator: function (val, otherVal) {
        if (val === null || val === undefined)
            return true;
        var res = true;
        return stringIsEnglish(val);
    },
    message: 'لطفا به زبان انگلیسی وارد کنید'
};
ko.validation.rules['userNameValidation'] = {
    validator: function (val, otherVal) {
        if (val === null || val === undefined)
            return true;
        return IsUserNameValid(val);
    },
    message: 'کاراکتر های مجاز شامل حروف فارسی و انگلیسی، اعداد، نقطه و علامت زیر خط (_) میباشند'
};
ko.validation.rules['persianOnly'] = {
    validator: function (val, otherVal) {
        if (val === null || val === undefined)
            return true;
        var res = true;
        val = val.replace(/\u200C/g, ' ').replace(/\&zwnj;/g, ' ');
        for (var i = 0, len = val.length; i < len; i++) {
            var target = val[i];
            if (/[^\u0600-\u06FF\s]/g.test(target)) {
                res = false;
            }
        }
        return res;
    },
    message: 'لطفا به زبان فارسی وارد کنید'
};
ko.validation.rules['notOnlyNumberAndSpChr'] = {
    validator: function (val, otherVal) {
        if (val === null || val === undefined)
            return true;
        var hasEngCharacters = false;
        var hasFaCharacters = false;
        var hasSpCharacters = false;
        var hasNumber = false;
        for (var i = 0, len = val.length; i < len; i++) {
            var target = val[i];
            if (/[\u0600-\u06FF]/g.test(target)) {
                hasFaCharacters = true;
            }
            if (/[%#@*+?^${}()|[\]\\]/g.test(target)) {
                hasSpCharacters = true;
            }
            if (/[a-zA-Z]/g.test(target)) {
                hasEngCharacters = true;
            }
            if (/[0-9]/g.test(target)) {
                hasNumber = true;
            }
        }

        if ((hasNumber === true || hasSpCharacters === true)
            && (hasFaCharacters === false && hasEngCharacters === false))
            return false;

        return true;
    },
    message: 'استفاده از علامت و اعداد به تنهایی مجاز نیست'
};
ko.validation.rules['notBeginNumberAndSpChr'] = {
    validator: function (val, otherVal) {
        if (val === null || val === undefined)
            return true;
        var hasSpCharacters = false;
        var hasNumber = false;
        var target = val[0];
        if (/[%#@*+?^${}()|[\]\\]/g.test(target)) {
            hasSpCharacters = true;
        }
        if (/[0-9]/g.test(target)) {
            hasNumber = true;
        }
        if (hasNumber === true || hasSpCharacters === true)
            return false;
        return true;
    },
    message: 'استفاده از علامت و اعداد در ابتدای رشته مجاز نیست'
};
ko.validation.rules['validCharacterName'] = {
    validator: function (val, otherVal) {
        if (val === null || val === undefined)
            return true;
        var isValidC = true;
        val = val.replace(/\u200C/g, ' ').replace(/\&zwnj;/g, ' ');
        for (var i = 0, len = val.length; i < len; i++) {
            var target = val[i];
            if (/[^a-zA-Z0-9\u0600-\u06FF\s\.\_()-]/g.test(target)) {
                isValidC = false;
            }
        }
        return isValidC;
    },
    message: 'کاراکترهای مجاز حروف فارسی،انگلیسی،اعداد،نقطه،خط فاصله،زیر خط و پرانتز می باشد'
};
ko.validation.rules['persianMobile'] = {
    validator: function (val, otherVal) {
        var mobileReg = /(0|\+98)?([ ]|-|[()]){0,2}9[1|2|3|4]([ ]|-|[()]){0,2}(?:[0-9]([ ]|-|[()]){0,2}){8}/ig;
        if (val !== null && val !== undefined && val !== "")
            return val.match(mobileReg);
        return true;
    },
    message: 'فرمت شماره تلفن همراه صحیح نیست'
};
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 = _h.countBackNumberZero(test);
                if (test.length - (afterParse.length + backZero) === 0) {
                    return true;
                } else {
                    return false;
                }
            }
        }
        return true;
    },
    message: ' فقط ورود اعداد مجاز است'
};
ko.validation.rules['phoneNumberCheck'] = {
    validator: function (val, otherVal) {
        if (val !== null && val !== undefined && val !== "") {
            var res;
            var test = val.toString();
            var a = parseInt(test);
            var afterParse = a.toString();
            if (afterParse.length <= 0)
                res = false;
            if (afterParse.length === test.length)
                res = true;
            else {
                var backZero = _h.countBackNumberZero(test);
                if (test.length - (afterParse.length + backZero) === 0) {
                    res = true;
                } else {
                    res = false;
                }
            }

            if (res === false || test.length > 15)
                return false;
            else {
                return true;
            }
        }
        return true;
    },
    message: 'شماره باید حتما عدد و حداکثر 15 کاراکتر باشد'
};
ko.validation.rules['shamsiYear'] = {
    validator: function (val, otherVal) {
        if (val === null || val === undefined || val === "")
            return true;
        var number = Number(val);
        if (number < 1350 || number > 1450)
            return false;
        return true;
    },
    message: 'لطفا سال را با قالب معتبر و کامل وارد کنید'
};
ko.validation.rules['notBeginWithZero'] = {
    validator: function (val, otherVal) {
        if (val === null || val === undefined || val === "")
            return true;
        var test = val.toString();
        var backZero = _h.countBackNumberZero(test);
        if (backZero > 0)
            return false;
        return true;
    },
    message: 'الگوی کد نباید با صفر شروع شود'
};
ko.validation.rules['atLeastOne'] = {
    validator: function (val, otherField) {
         return val.length > 0;
    },
    message: 'لطفا حداقل یک مجوز برای این سمت انتخاب کنید'
};
ko.validation.rules['treeFiscalValueValidate'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (val, otherField, validate) {
        if (val === null || val === undefined || val === "")
            return true;
        if (_h.isNumeric(val)) {
            if (val.toString().indexOf('.') !== -1)
                return false;
            var a = val.toString().length;
            var isNegative = Number(val) < 0;
            if (isNegative && a <= 28)
                return true;
            if (!isNegative && a <= 29)
                return true;
        }
        return false;
    },
    message: 'مقدار ارزش گره در درختواره های مالی باید شامل اعداد صحیح و حداکثر 29 رقم باشد'
};
ko.validation.rules['treeNumeralDecimalValueValidate'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (val, otherField, validate) {
        if (val === null || val === undefined || val === "")
            return true;
        if (_h.isNumeric(val)) {
            var a = val.toString().length;
            var isNegative = Number(val) < 0;
            if (isNegative && a <= 28)
                return true;
            if (!isNegative && a <= 29)
                return true;
        }
        return false;
    },
    message: 'مقدار ارزش گره در درختواره های عددی فقط باید شامل اعداد صحیح و اعشاری و حداکثر 29 رقم باشد'
};
ko.validation.rules['treeNumeralValueValidate'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (val, otherField, validate) {
        if (val === null || val === undefined || val === "")
            return true;
        if (_h.isNumeric(val)) {
            if (val.toString().indexOf('.') !== -1)
                return false;
            var a = val.toString().length;
            var isNegative = Number(val) < 0;
            if (isNegative && a <= 28)
                return true;
            if (!isNegative && a <= 29)
                return true;
        }

        return false;
    },
    message: 'مقدار ارزش گره در درختواره های عددی فقط باید شامل اعداد صحیح و حداکثر 29 رقم باشد'
};
ko.validation.rules['treeNonNumeralValueValidate'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (val, otherField, validate) {
        if (val === null || val === undefined || val === "")
            return true;
        if (val.toString().length <= 255)
            return true;
        return false;
    },
    message: 'مقدار ارزش گره در درختواره های غیر عددی باید حداکثر 255 کاراکتر باشد'
};
ko.validation.rules['onlyOneYearDef'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (val, otherField, callback) {
        var b = this.getValue(otherField.params[0]);
        if (val === null || val === undefined || val === "")
            return true;
        if (b === null || b === undefined || b === "")
            return true;
        var date = new Date(val);
        var date2 = new Date(b);
        var isleap = dateHelper.isLeapGregorianYear(date.getFullYear());
        var days = dateHelper.daysBetween(date, date2);
        if ((days <= 365 && !isleap) || (days <= 366 && isleap)) {
            return true;
        }
        return false;
    },
    message: 'فاصله میان تاریخ شروع و پایان دوره نمی تواند بیش از یک سال باشد'
};
ko.validation.rules['beforeEndDate'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (val, otherField, callback) {
        var endDate = this.getValue(otherField.params[0]);
        if (val === null || val === undefined || val === "")
            return true;
        if (endDate === null || endDate === undefined || endDate === "")
            return true;
        var date = new Date(val);
        var date2 = new Date(endDate);
        var res = dateHelper.compare(date, date2);
        return res === 2;
    },
    message: 'تاریخ شروع دوره مالی نمی تواند بعد از تاریخ پایان دوره باشد'
};
ko.validation.rules['afterStartDate'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (val, otherField, callback) {
        var startDate = this.getValue(otherField.params[0]);
        if (val === null || val === undefined || val === "")
            return true;
        if (startDate === null || startDate === undefined || startDate === "")
            return true;
        var date = new Date(startDate);
        var date2 = new Date(val);
        var res = dateHelper.compare(date, date2);
        return res === 2;
    },
    message: 'تاریخ پایان دوره مالی نمی تواند قبل از تاریخ شروع دوره باشد'
};
ko.validation.rules['countValue'] = {
    validator: function (val, otherVal) {
        if (val === null || val === undefined || val > 0)
            return true;

        return false;
    },
    message: 'لطفا تعداد را وارد نمایید'
};
ko.validation.rules['priceValue'] = {
    validator: function (val, otherVal) {
        if (val === null || val === undefined || val > 0)
            return true;

        return false;
    },
    message: 'لطفا مبلغ را وارد نمایید'
};
ko.validation.rules['periodIdValue'] = {
    validator: function (val, otherVal) {
        if (val > 0)
            return true;

        return false;
    },
    message: 'لطفا دوره مالی مورد نظر خود را از لیست انتخاب کنید'
};
ko.validation.rules['atLeastSelectedOneTree'] = {
    validator: function (val, otherField) {
        if (val.length > 0) {
            return true;
        }
        return false;
    },
    message: 'انتخاب حداقل یک درختواره الزامی است'
};
ko.validation.rules['remoteIsPeriodUniqueValidationRule'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    async: true,
    validator: function (val, otherField, callback) {
        if (!val)
            return true;
        var value = this.getValue(otherField.params[0]);
        if (value === null || value === undefined)
            value = 0;
        var periodState = this.getValue(otherField.params[1]);
        if (periodState === null || periodState === undefined) {
            return false;
        }
        var auditState = this.getValue(otherField.params[2]);
        if (auditState === null || auditState === undefined) {
            return false;
        }

        var startDate = this.getValue(otherField.params[3]);
        if (startDate === null || startDate === undefined) {
            return false;
        }

        var periodType = this.getValue(otherField.params[4]);
        if (periodType === null || periodType === undefined) {
            return false;
        }

       
        ApiService.request({
            url: "postIsUnique",
            data: {
                controllerName: 6,
                inputData: {
                    id: value,
                    endDate: val,
                    periodState: periodState,
                    auditState: auditState,
                    startDate: startDate,
                    periodType: periodType
                }
            },
            success: function (data) {
                callback(data);
            },
            error: function (data) {

            }
        });

    },
    message: 'هم اکنون دوره مالی مشابهی برای این تاریخ ثبت شده است'
};
ko.validation.rules['remoteIsValidateFormula'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    async: true,
    validator: function (val, otherField, callback) {
        if (val === null || val === undefined || val === "" || val === "undefined")
            return true;
        
        var model = {
                formula: val.toString(),
                controllerName: otherField
            };
        if(typeof otherField === 'object' && otherField !== null)
        {
            model.controllerName = otherField.params;
        }
        
        ApiService.request(
            {
                url: "/api/common/postisValidFormula",
                data:model,
                success: function (data) {
                    callback(data);
                },
                error: function (data) {

                }
            });
        return true;
    },
    message: 'فرمت فرمول صحیح نیست'
};
ko.validation.rules['remoteIsValidExpression'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    async: true,
    validator: function (val, otherField, callback) {
        if (val !== null && val !== undefined && val !== "") {
            ApiService.request(
                {
                    url: "/api/common/postisvalidexpression",
                    data: {
                        data: val.toString(),
                        isCondition: otherField[0],
                        isFormula: otherField[1],
                        controllerName: otherField[2]
                    },
                    success: function (data) {
                        callback(data);
                    },
                    error: function (data) {

                    }
                });
        }
        return true;
    },
    message: function (params, observable, hg) {
        return 'فرمت عبارت تجمیع شروط نامعتبر است';
    }

};
ko.validation.rules['isAllConditionsUse'] = {
    newParam: "",
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (phrase, otherField, callback) {
        var conditions = this.getValue(otherField.params);
        if (conditions.length < 2)
            return true;
        if (_h.isNullOrEmpty(phrase) || phrase === "")
            return false;
        var all = true;
        for (var i = 0; i < conditions.length; i++) {
            var cName = "cs" + (i + 1);
            if (phrase.toLowerCase().indexOf(cName) === -1)
                all = false;
        }
        return all;
    },
    message: function (params, observable, hg) {
        return 'استفاده از همه شرط های تعریف شده، در تجمیع شروط الزامی است';
    }
};
ko.validation.rules['isConditionsUseValid'] = {
    newParam: "",
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (phrase, otherField, callback) {
        var conditions = this.getValue(otherField.params);
        if (conditions.length < 2)
            return true;


        var array = [];
        for (var i = 0; i < conditions.length; i++) {
            var target = conditions[i];
            if (!target.validationObject.isValid()) {
                array.push(i + 1);
            }
        }
        if (array.length > 0) {
            //newParam = array;
            return false;
        }

        return true;
    },
    message: function (params, observable, hg) {
        return 'یکی از شرط های موجود در تجمیع شروط، صحیح نمی باشد';
    }
};
ko.validation.rules['atleastOneDestinationValues'] = {
    validator: function (val, otherField) {
        if (val.length > 0) {
            var res = false;
            $.each(val, function (i, p) {
                if (!_h.isNullOrEmpty(p.destinationField()) &&
                    !_h.isNullOrEmpty(p.calculationValueType()) &&
                    !_h.isNullOrEmpty(p.value()) && p.value() !== "")
                    res = true;
            });
            return res;
        }
        return false;
    },
    message: 'تعیین روش مقداردهی باید حداقل برای یکی از ستونهای مقصد انجام شود'
};
ko.validation.rules['atleastOneDeleteCostDestinationValues'] = {
    validator: function (val, otherField) {
        if (val.length > 0) {
            var res = false;
            $.each(val, function (i, p) {
                if (!_h.isNullOrEmpty(p.sourceFieldOrder()) &&
                    !_h.isNullOrEmpty(p.destinationFieldOrder()))
                    res = true;
            });
            return res;
        }
        return false;
    },
    message: 'تعیین روش مقداردهی باید حداقل برای یکی از ستونهای مقصد انجام شود'
};
ko.validation.rules['atleastOneColumnDestinationValues'] = {
    validator: function (val, otherField) {
        if (val.length > 0) {
            var res = false;
            $.each(val, function (i, p) {
                if (!_h.isNullOrEmpty(p.nodeId()) &&
                    !_h.isNullOrEmpty(p.columnFunction()) &&
                    !_h.isNullOrEmpty(p.fieldOrder()))
                    res = true;
            });
            return res;
        }
        return false;
    },
    message: 'تعیین روش مقداردهی باید حداقل برای یکی از برگ های درخت منتخب انجام شود'
};
ko.validation.rules['atleastOnesourceFieldFormulas'] = {
    validator: function (val, otherField) {
        if (val.length > 0) {
            var res = false;
            $.each(val, function (i, p) {
                if (!_h.isNullOrEmpty(p.fieldOrder()) && !_h.isNullOrEmpty(p.computeType()) &&
                    !_h.isNullOrEmpty(p.value()))
                    res = true;
            });
            return res;
        }
        return false;
    },
    message: 'تعیین مقدار باید حداقل برای یکی از ستونهای جدول مبدا انجام شود'
};
ko.validation.rules['onlyDecimal'] = {
    validator: function (val, validate) {
        return val !== null && val !== "" && /^-?\d*(?:\.\d*)?$/.test(val.toString());
    },
    message: 'فقط ورود اعداد مجاز است'
};
ko.validation.rules['onlyTenDigitDecimal'] = {
    validator: function (val, fg, validate) {
        if (_h.isNullOrEmpty(val) ||
            val.toString().indexOf(".") === -1)
            return true;
        var decimalPart = val.toString().split(".")[1];
        return decimalPart && decimalPart.length <= 10;
    },
    message: 'حداکثر تا 10 رقم اعشار مجاز است'
};
ko.validation.rules['max29Digit'] = {
    validator: function (val, fg, validate) {
        if (val === null || val === undefined || val === "")
            return true;
        if (_h.isNumeric(val)) {
            var a = val.toString().length;
            var isNegative = Number(val) < 0;
            if (isNegative && a <= 28)
                return true;
            if (!isNegative && a <= 29)
                return true;
        }
        return false;
    },
    message: 'حداکثر تا 29 رقم مجاز است'
};
ko.validation.rules['pageRangeValidate'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (val, otherField, callback) {
        var pageFrom = this.getValue(otherField[0]);
        var pageTo = this.getValue(otherField[1]);
        var pageCount = this.getValue(otherField[2]);
        if (!pageFrom || !pageTo)
            return true;
        pageFrom = Number(pageFrom);
        pageTo = Number(pageTo);
        pageCount = pageCount.length;
        this.newParam = pageCount;
        if (pageFrom < 1 || pageFrom > pageCount)
            return false;
        if (pageTo < pageFrom || pageTo < 1 || pageFrom > pageCount || pageTo > pageCount)
            return false;
        return true;
    },
    message: function (params, observable, hg) {
        var pageCount = params[2]().length;
        return 'محدوده صفحات انتخاب شده باید حداقل یک و حداکثر ' + pageCount + ' باشد';
    }
};
ko.validation.rules['chkStringTypeCell'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (val, otherField, callback) {
        var parent = this.getValue(otherField[0]);
        if (_h.isNullOrEmpty(val))
            return true;
        var model = $("#rg-" + parent.id).rg("getModel");
        var firstCell = model.cells.filter(a => a.address === val)[0];
        if (firstCell) {
            if (firstCell.extraParams.dataType === 2)
                return false;
        }
        return true;
    },
    message: 'انتخاب سلول های متنی جهت مقایسه مجاز نیست'
};
ko.validation.rules['chkErrorRate'] = {
    validator: function (val, otherVal) {
        if (_h.isEmpty(val) || val == 0)
            return true;
        var isValid = true;
        for (var i = 0, len = val.length; i < len; i++) {
            var target = val[i];
            if (/[%]/g.test(target) === false && /[0-9]/g.test(target) === false)
                isValid = false;
        }
        return isValid;
    },
    message: 'فقط اعداد و علامت % مجاز است'
};
ko.validation.rules['chkPercentRate'] = {
    validator: function (val, otherVal) {
        if (_h.isEmpty(val) || val == 0 || val.indexOf("%") === -1)
            return true;
        var isValid = true;
        var hasNumber = false;
        for (var i = 0, len = val.length; i < len; i++) {
            var target = val[i];
            if (/[0-9]/g.test(target) === true)
                hasNumber = true;
        }

        if (!hasNumber)
            isValid = false;
        var number = val.trim().replace("%", "");
        if (number && Number(number) > 100)
            isValid = false;


        return isValid;
    },
    message: 'علامت % بهمراه عدد کوچکتر یا مساوی 100 مجاز است'
};
ko.validation.rules['duplicateCell'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (val, otherField, callback) {
        var parent = this.getValue(otherField[0]);
        if (_h.isNullOrEmpty(val))
            return true;
        var model = $("#rg-" + parent.id).rg("getModel");
        var firstCell = model.cells.filter(a => a.address === val)[0];
        if (firstCell) {
            var count = 0;
            for (var i = 0; i < parent.cellBinds().length; i++) {
                var target = parent.cellBinds()[i];
                if (target.firstCell() === firstCell.address || target.secondCell() === firstCell.address)
                    count++;
            }

            if (count > 1)
                return false;
        }
        return true;
    },
    message: 'هر سلول فقط یکبار میتواند مورد مقایسه قرار بگیرد'
};
ko.validation.rules['compareSameCell'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (val, otherField, callback) {
        var parent = this.getValue(otherField[0]);
        var second = this.getValue(otherField[1]);
        if (_h.isNullOrEmpty(val) || _h.isNullOrEmpty(second))
            return true;
        var model = $("#rg-" + parent.id).rg("getModel");
        var firstCell = model.cells.filter(a=> a.address === val)[0];
        var secondCell = model.cells.filter(a => a.address === second)[0];
        if (firstCell && secondCell) {
            if (firstCell.address === secondCell.address)
                return false;
        }
        return true;
    },
    message: 'امکان مقایسه سلول با خودش وجود ندارد'
};
ko.validation.rules['noEqualPeriod'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    validator: function (val, otherField, callback) {
        var first = this.getValue(otherField.params[0]);
        var second = this.getValue(otherField.params[1]);
        if (first > 0 && val > 0 && first === val)
            return false;
        if (second > 0 && val > 0 && second === val)
            return false;
        return true;
    },
    message: 'انتخاب دوره های مالی مشابه جهت مقایسه مجاز نیست'
};
ko.validation.rules['remoteIsUniqueRule'] = {
    getValue: function (o) {
        return (typeof o === 'function' ? o() : o);
    },
    async: true,
    validator: function (val, otherField, callback) {
        if (!val)
            return true;
        var value = this.getValue(otherField.params[0]);
        if (value === null || value === undefined)
            value = 0;

        var co = _h.findControllerName(otherField.params[1]);
        var model = {
            propertyName: otherField.params[2],
            id: value,
            value: val.toString()
        };
        if (otherField.params.length > 3) {
            var adjustmentId = this.getValue(otherField.params[3]);
            if (adjustmentId === null || adjustmentId === undefined)
                adjustmentId = 0;
            model.adjustmentId = adjustmentId;
        }        
        
      

        ApiService.request(
            {
                url: "postIsUnique",
                data: {
                    controllerName: co,
                    inputData: model
                },
                success: function (data) {
                    callback(data);
                },
                error: function (data) {
                }
            });
    },
    message: function (model, observable, hg) {
            return toast.createVMessage(model.params);
    }
};