(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[45],{

/***/ 121:
/***/ (function(module, exports) {

module.exports = {
    isPrimitiveValue(value) {
        if (typeof value == 'string') return true;
        if (typeof value == 'number' && isFinite(value)) return true;
        if (typeof value == 'boolean') return true;
        return false;
    },

    looksLikeNumber(value) {
        if (!isNaN(+value)) return true;
        return false;
    },

    isObject(obj) {
        return Object(obj) === obj && Object.getPrototypeOf(obj) === Object.prototype;
    },

    isEmptyObject(map) {
        for (const key in map) {
            if (map.hasOwnProperty(key)) {
                return false;
            }
        }
        return true;
    },

    escapeRegExp(str) {
        return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
    },

    isNoValue(value) {
        return value === undefined || value === null || value === '';
    }
};


/***/ }),

/***/ 2804:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function required() {
    return value => {
        if (util.isNoValue(value)) {
            return 'REQUIRED';
        }

        return;
    };
};

module.exports = required;

/***/ }),

/***/ 2805:
/***/ (function(module, exports) {

function not_empty() {
    return value => {
        if (value !== null && value !== undefined && value === '') {
            return 'CANNOT_BE_EMPTY';
        }

        return;
    };
}

module.exports = not_empty;

/***/ }),

/***/ 2806:
/***/ (function(module, exports) {

function not_empty_list() {
    return list => {
        if (list === undefined || list === '') return 'CANNOT_BE_EMPTY';
        if (!Array.isArray(list)) return 'FORMAT_ERROR';
        if (list.length < 1) return 'CANNOT_BE_EMPTY';
        return;
    };
};

module.exports = not_empty_list;

/***/ }),

/***/ 2807:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function any_object() {
    return value => {
        if (util.isNoValue(value)) return;

        if (!util.isObject(value)) {
            return 'FORMAT_ERROR';
        }
    };
};

module.exports = any_object;

/***/ }),

/***/ 2808:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function string() {
    return (value, params, outputArr) => {
        if (util.isNoValue(value)) return;
        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';

        outputArr.push(value + '');
        return;
    };
}

module.exports = string;

/***/ }),

/***/ 2809:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function eq(allowedValue) {
    return (value, params, outputArr) => {
        if (util.isNoValue(value)) return;
        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';

        if (value + '' === allowedValue + '') {
            outputArr.push(allowedValue);
            return;
        }

        return 'NOT_ALLOWED_VALUE';
    };
}

module.exports = eq;

/***/ }),

/***/ 2810:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function one_of(allowedValues) {
    if (!Array.isArray(allowedValues)) {
        allowedValues = Array.prototype.slice.call(arguments);
        allowedValues.pop(); // pop ruleBuilders
    }

    return (value, params, outputArr) => {
        if (util.isNoValue(value)) return;

        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';

        for (const allowedValue of allowedValues) {
            if (value + '' === allowedValue + '') {
                outputArr.push(allowedValue);
                return;
            }
        }

        return 'NOT_ALLOWED_VALUE';
    };
}

module.exports = one_of;

/***/ }),

/***/ 2811:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);
 
function max_length(maxLength) {
    return (value, params, outputArr) => {
        if (util.isNoValue(value)) return;
        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';

        value += '';
        if (value.length > maxLength) return 'TOO_LONG';
        outputArr.push(value);
    };
}

module.exports = max_length;

/***/ }),

/***/ 2812:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function min_length(minLength) {
    return (value, params, outputArr) => {
        if (util.isNoValue(value)) return;
        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';

        value += '';
        if (value.length < minLength) return 'TOO_SHORT';
        outputArr.push(value);
    };
}

module.exports = min_length;

/***/ }),

/***/ 2813:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function length_equal(length) {
    return (value, params, outputArr) => {
        if (util.isNoValue(value)) return;
        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';

        value += '';
        if (value.length < length) return 'TOO_SHORT';
        if (value.length > length) return 'TOO_LONG';
        outputArr.push(value);
    };
}

module.exports = length_equal;

/***/ }),

/***/ 2814:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function length_between(minLength, maxLength) {
    return (value, params, outputArr) => {
        if (util.isNoValue(value)) return;
        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';

        value += '';
        if (value.length < minLength) return 'TOO_SHORT';
        if (value.length > maxLength) return 'TOO_LONG';
        outputArr.push(value);
    };
}

module.exports = length_between;

/***/ }),

/***/ 2815:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function like(reStr, flags) {
    const isIgnoreCase = arguments.length === 3 && flags.match('i');
    const re = new RegExp(reStr, isIgnoreCase ? 'i' : '');

    return (value, params, outputArr) => {
        if (util.isNoValue(value)) return;

        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';

        value += '';
        if (!value.match(re)) return 'WRONG_FORMAT';
        outputArr.push(value);
    };
}

module.exports = like;

/***/ }),

/***/ 2816:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function integer() {
    return (value, params, outputArr) => {
        if (util.isNoValue(value)) return;
        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';
        if (!util.looksLikeNumber(value)) return 'NOT_INTEGER';

        if (!Number.isInteger(+value)) return 'NOT_INTEGER';
        outputArr.push(+value);
    };
}

module.exports = integer;

/***/ }),

/***/ 2817:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function positive_integer() {
    return (value, params, outputArr) => {
        if (util.isNoValue(value)) return;
        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';
        if (!util.looksLikeNumber(value)) return 'NOT_POSITIVE_INTEGER';

        if (!Number.isInteger(+value) || +value < 1) return 'NOT_POSITIVE_INTEGER';
        outputArr.push(+value);
    };
}

module.exports = positive_integer;

/***/ }),

/***/ 2818:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function decimal() {
    return (value, params, outputArr) => {
        if (util.isNoValue(value)) return;
        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';
        if (!util.looksLikeNumber(value)) return 'NOT_DECIMAL';

        value += '';
        if (!/^(?:\-?(?:(?:[0-9]+\.[0-9]+)|(?:[0-9]+)))$/.test(value)) return 'NOT_DECIMAL';
        outputArr.push(+value);
    };
}

module.exports = decimal;

/***/ }),

/***/ 2819:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function positive_decimal() {
    return (value, params, outputArr) => {
        if (util.isNoValue(value)) return;
        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';
        if (!util.looksLikeNumber(value)) return 'NOT_POSITIVE_DECIMAL';

        value += '';
        if (!/^(?:(?:[0-9]*\.[0-9]+)|(?:[1-9][0-9]*))$/.test(value))
            return 'NOT_POSITIVE_DECIMAL';
        outputArr.push(+value);
    };
}

module.exports = positive_decimal;


/***/ }),

/***/ 2820:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function max_number(maxNumber) {
    return (value, params, outputArr) => {
        if (util.isNoValue(value)) return;
        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';
        if (!util.looksLikeNumber(value)) return 'NOT_NUMBER';

        if (+value > +maxNumber) return 'TOO_HIGH';
        outputArr.push(+value);
    };
}

module.exports = max_number;

/***/ }),

/***/ 2821:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function min_number(minNumber) {
    return (value, params, outputArr) => {
        if (util.isNoValue(value)) return;
        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';
        if (!util.looksLikeNumber(value)) return 'NOT_NUMBER';

        if (+value < +minNumber) return 'TOO_LOW';
        outputArr.push(+value);
    };
}

module.exports = min_number;

/***/ }),

/***/ 2822:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function number_between(minNumber, maxNumber) {
    return (value, params, outputArr) => {
        if (util.isNoValue(value)) return;
        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';
        if (!util.looksLikeNumber(value)) return 'NOT_NUMBER';

        if (+value < +minNumber) return 'TOO_LOW';
        if (+value > +maxNumber) return 'TOO_HIGH';
        outputArr.push(+value);
    };
}

module.exports = number_between;

/***/ }),

/***/ 2823:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function email() {
    var emailRe = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

    return value => {
        if (util.isNoValue(value)) return;
        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';

        value += '';
        if (!emailRe.test(value)) return 'WRONG_EMAIL';
        if (/\@.*\@/.test(value)) return 'WRONG_EMAIL';
        if (/\@.*_/.test(value)) return 'WRONG_EMAIL';
        return;
    };
}

module.exports = email;

/***/ }),

/***/ 2824:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function equal_to_field(field) {
    return (value, params) => {
        if (util.isNoValue(value)) return;
        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';

        if (value != params[field]) return 'FIELDS_NOT_EQUAL';
        return;
    };
}

module.exports = equal_to_field;

/***/ }),

/***/ 2825:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function url() {
    const urlReStr =
        '^(?:(?:http|https)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[0-1]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))\\.?|localhost)(?::\\d{2,5})?(?:[/?#]\\S*)?$';
    const urlRe = new RegExp(urlReStr, 'i');

    return value => {
        if (util.isNoValue(value)) return;
        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';

        if (value.length < 2083 && urlRe.test(value)) return;
        return 'WRONG_URL';
    };
}

module.exports = url;

/***/ }),

/***/ 2826:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function iso_date() {
    return value => {
        if (util.isNoValue(value)) return;
        if (!util.isPrimitiveValue(value)) return 'FORMAT_ERROR';

        const matched = value.match(/^(\d{4})-([0-1][0-9])-([0-3][0-9])$/);

        if (matched) {
            const epoch = Date.parse(value);
            if (!epoch && epoch !== 0) return 'WRONG_DATE';

            const d = new Date(epoch);
            d.setTime(d.getTime() + d.getTimezoneOffset() * 60 * 1000);

            if (
                d.getFullYear() == matched[1] &&
                d.getMonth() + 1 == +matched[2] &&
                d.getDate() == +matched[3]
            ) {
                return;
            }
        }

        return 'WRONG_DATE';
    };
}

module.exports = iso_date;

/***/ }),

/***/ 2827:
/***/ (function(module, exports, __webpack_require__) {

const Validator = __webpack_require__(469);
const util = __webpack_require__(121);

function nested_object(livr, ruleBuilders) {
    const validator = new Validator(livr).registerRules(ruleBuilders).prepare();

    return (nestedObject, params, outputArr) => {
        if (util.isNoValue(nestedObject)) return;
        if (!util.isObject(nestedObject)) return 'FORMAT_ERROR';

        const result = validator.validate(nestedObject);

        if (result) {
            outputArr.push(result);
            return;
        } else {
            return validator.getErrors();
        }
    };
}

module.exports = nested_object;

/***/ }),

/***/ 2828:
/***/ (function(module, exports, __webpack_require__) {

const Validator = __webpack_require__(469);
const util = __webpack_require__(121);

function variable_object(selectorField, livrs, ruleBuilders) {
    const validators = {};

    for (const selectorValue in livrs) {
        const validator = new Validator(livrs[selectorValue])
            .registerRules(ruleBuilders)
            .prepare();
        validators[selectorValue] = validator;
    }

    return (object, params, outputArr) => {
        if (util.isNoValue(object)) return;

        if (
            !util.isObject(object) ||
            !object[selectorField] ||
            !validators[object[selectorField]]
        ) {
            return 'FORMAT_ERROR';
        }

        const validator = validators[object[selectorField]];
        const result = validator.validate(object);

        if (result) {
            outputArr.push(result);
            return;
        } else {
            return validator.getErrors();
        }
    };
}

module.exports = variable_object;


/***/ }),

/***/ 2829:
/***/ (function(module, exports, __webpack_require__) {

const Validator = __webpack_require__(469);
const util = __webpack_require__(121);

function list_of(rules, ruleBuilders) {
    if (!Array.isArray(rules)) {
        rules = Array.prototype.slice.call(arguments);
        ruleBuilders = rules.pop();
    }

    const livr = { field: rules };
    const validator = new Validator(livr).registerRules(ruleBuilders).prepare();

    return (values, params, outputArr) => {
        if (util.isNoValue(values)) return;

        if (!Array.isArray(values)) return 'FORMAT_ERROR';

        const results = [];
        const errors = [];
        let hasErrors = false;

        for (const value of values) {
            const result = validator.validate({ field: value });

            if (result) {
                results.push(result.field);
                errors.push(null);
            } else {
                hasErrors = true;
                errors.push(validator.getErrors().field);
                results.push(null);
            }
        }

        if (hasErrors) {
            return errors;
        } else {
            outputArr.push(results);
            return;
        }
    };
}

module.exports = list_of;

/***/ }),

/***/ 2830:
/***/ (function(module, exports, __webpack_require__) {

const Validator = __webpack_require__(469);
const util = __webpack_require__(121);

function list_of_objects(livr, ruleBuilders) {
    const validator = new Validator(livr).registerRules(ruleBuilders).prepare();

    return (objects, params, outputArr) => {
        if (util.isNoValue(objects)) return;
        if (!Array.isArray(objects)) return 'FORMAT_ERROR';

        const results = [];
        const errors = [];
        let hasErrors = false;

        for (const object of objects) {
            const result = validator.validate(object);

            if (result) {
                results.push(result);
                errors.push(null);
            } else {
                hasErrors = true;
                errors.push(validator.getErrors());
                results.push(null);
            }
        }

        if (hasErrors) {
            return errors;
        } else {
            outputArr.push(results);
            return;
        }
    };
}

module.exports = list_of_objects;

/***/ }),

/***/ 2831:
/***/ (function(module, exports, __webpack_require__) {

const Validator = __webpack_require__(469);

function or() {
    const ruleSets = Array.prototype.slice.call(arguments);
    const ruleBuilders = ruleSets.pop();

    const validators = ruleSets.map(rules => {
        const livr = { field: rules };
        const validator = new Validator(livr).registerRules(ruleBuilders).prepare();

        return validator;
    });

    return (value, params, outputArr) => {
        let lastError;

        for (const validator of validators) {
            const result = validator.validate({ field: value });

            if (result) {
                outputArr.push(result.field);
                return;
            } else {
                lastError = validator.getErrors().field;
            }
        }

        return lastError;
    };
}

module.exports = or;

/***/ }),

/***/ 2832:
/***/ (function(module, exports, __webpack_require__) {

const Validator = __webpack_require__(469);
const util = __webpack_require__(121);

function list_of_different_objects(selectorField, livrs, ruleBuilders) {
    const validators = {};

    for (const selectorValue in livrs) {
        const validator = new Validator(livrs[selectorValue])
            .registerRules(ruleBuilders)
            .prepare();
        validators[selectorValue] = validator;
    }

    return (objects, params, outputArr) => {
        if (util.isNoValue(objects)) return;
        if (!Array.isArray(objects)) return 'FORMAT_ERROR';

        const results = [];
        const errors = [];
        let hasErrors = false;

        for (const object of objects) {
            if (
                typeof object != 'object' ||
                !object[selectorField] ||
                !validators[object[selectorField]]
            ) {
                errors.push('FORMAT_ERROR');
                continue;
            }

            const validator = validators[object[selectorField]];
            const result = validator.validate(object);

            if (result) {
                results.push(result);
                errors.push(null);
            } else {
                hasErrors = true;
                errors.push(validator.getErrors());
                results.push(null);
            }
        }

        if (hasErrors) {
            return errors;
        } else {
            outputArr.push(results);
            return;
        }
    };
}

module.exports = list_of_different_objects;

/***/ }),

/***/ 2833:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

module.exports = defaultValue => {
    return (value, params, outputArr) => {
        if (util.isNoValue(value)) {
            outputArr.push(defaultValue);
        }
    };
}




/***/ }),

/***/ 2834:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function trim() {
    return (value, params, outputArr) => {
        if (util.isNoValue(value) || typeof value === 'object') return;

        value += ''; // TODO just do not trim numbers
        outputArr.push(value.replace(/^\s*/, '').replace(/\s*$/, ''));
    };
}

module.exports = trim;

/***/ }),

/***/ 2835:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function to_lc() {
    return (value, params, outputArr) => {
        if (util.isNoValue(value) || typeof value === 'object') return;

        value += ''; // TODO just skip numbers
        outputArr.push(value.toLowerCase());
    };
}

module.exports = to_lc;

/***/ }),

/***/ 2836:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function to_uc() {
    return (value, params, outputArr) => {
        if (util.isNoValue(value) || typeof value === 'object') return;

        value += ''; // TODO just skip numbers
        outputArr.push(value.toUpperCase());
    };
}

module.exports = to_uc;

/***/ }),

/***/ 2837:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function remove(chars) {
    chars = util.escapeRegExp(chars);
    const re = new RegExp('[' + chars + ']', 'g');

    return (value, params, outputArr) => {
        if (util.isNoValue(value) || typeof value === 'object') return;

        value += ''; // TODO just skip numbers
        outputArr.push(value.replace(re, ''));
    };
}

module.exports = remove;

/***/ }),

/***/ 2838:
/***/ (function(module, exports, __webpack_require__) {

const util = __webpack_require__(121);

function leave_only(chars) {
    chars = util.escapeRegExp(chars);
    const re = new RegExp('[^' + chars + ']', 'g');

    return (value, params, outputArr) => {
        if (util.isNoValue(value) || typeof value === 'object') return;

        value += ''; // TODO just skip numbers
        outputArr.push(value.replace(re, ''));
    };
}

module.exports = leave_only;

/***/ }),

/***/ 2853:
/***/ (function(module, exports, __webpack_require__) {

const Validator = __webpack_require__(469);
const util = __webpack_require__(121);

const rules = {
    required:         __webpack_require__(2804),
    not_empty:        __webpack_require__(2805),
    not_empty_list:   __webpack_require__(2806),
    any_object:       __webpack_require__(2807),

    string:           __webpack_require__(2808),
    eq:               __webpack_require__(2809),
    one_of:           __webpack_require__(2810),
    max_length:       __webpack_require__(2811),
    min_length:       __webpack_require__(2812),
    length_equal:     __webpack_require__(2813),
    length_between:   __webpack_require__(2814),
    like:             __webpack_require__(2815),

    integer:          __webpack_require__(2816),
    positive_integer: __webpack_require__(2817),
    decimal:          __webpack_require__(2818),
    positive_decimal: __webpack_require__(2819),
    max_number:       __webpack_require__(2820),
    min_number:       __webpack_require__(2821),
    number_between:   __webpack_require__(2822),

    email:            __webpack_require__(2823),
    equal_to_field:   __webpack_require__(2824),
    url:              __webpack_require__(2825),
    iso_date:         __webpack_require__(2826),

    nested_object:    __webpack_require__(2827),
    variable_object:  __webpack_require__(2828),
    list_of:          __webpack_require__(2829),
    list_of_objects:  __webpack_require__(2830),
    or:               __webpack_require__(2831),
    list_of_different_objects: __webpack_require__(2832),

    default:          __webpack_require__(2833),
    trim:             __webpack_require__(2834),
    to_lc:            __webpack_require__(2835),
    to_uc:            __webpack_require__(2836),
    remove:           __webpack_require__(2837),
    leave_only:       __webpack_require__(2838)
};

Validator.registerDefaultRules(rules);

module.exports = { Validator, rules, util };


/***/ }),

/***/ 469:
/***/ (function(module, exports, __webpack_require__) {

"use strict";


const util = __webpack_require__(121);

const DEFAULT_RULES = {};
let IS_DEFAULT_AUTO_TRIM = 0;

class Validator {
    constructor(livrRules, isAutoTrim) {
        this.isPrepared = false;
        this.livrRules = livrRules;
        this.validators = {};
        this.validatorBuilders = {};
        this.errors = null;

        if (isAutoTrim !== null && isAutoTrim !== undefined) {
            this.isAutoTrim = isAutoTrim;
        } else {
            this.isAutoTrim = IS_DEFAULT_AUTO_TRIM;
        }

        this.registerRules(DEFAULT_RULES);
    }

    static getDefaultRules() {
        return DEFAULT_RULES;
    }

    static registerAliasedDefaultRule(alias) {
        if (!alias.name) throw 'Alias name required';

        DEFAULT_RULES[alias.name] = this._buildAliasedRule(alias.rules, alias.error);
    }

    static registerDefaultRules(rules) {
        for (const ruleName in rules) {
            DEFAULT_RULES[ruleName] = rules[ruleName];
        }
    }

    static defaultAutoTrim(isAutoTrim) {
        IS_DEFAULT_AUTO_TRIM = !!isAutoTrim;
    }

    static _buildAliasedRule(rules, errorCode) {
        if (!rules) throw 'Alias rules required';

        const livr = { value: rules };

        return ruleBuilders => {
            // ruleBuilders comes always as a last argument
            // we register them to support custom rules in aliases
            const validator = new Validator(livr).registerRules(ruleBuilders).prepare();

            return (value, undefined, outputArr) => {
                const result = validator.validate({ value });

                if (result) {
                    outputArr.push(result.value);
                    return;
                } else {
                    return errorCode || validator.getErrors().value;
                }
            };
        };
    }

    prepare() {
        const allRules = this.livrRules;

        for (const field in allRules) {
            let fieldRules = allRules[field];

            if (!Array.isArray(fieldRules)) {
                fieldRules = [fieldRules];
            }

            const validators = [];

            for (const fieldRule of fieldRules) {
                const parsed = this._parseRule(fieldRule);
                validators.push(this._buildValidator(parsed.name, parsed.args));
            }

            this.validators[field] = validators;
        }

        this.isPrepared = true;
        return this;
    }

    validate(data) {
        if (!this.isPrepared) this.prepare();

        if (!util.isObject(data)) {
            this.errors = 'FORMAT_ERROR';
            return;
        }

        if (this.isAutoTrim) {
            data = this._autoTrim(data);
        }

        const errors = {};
        const result = {};

        for (const fieldName in this.validators) {
            const validators = this.validators[fieldName];
            if (!validators || !validators.length) continue;

            const value = data[fieldName];

            for (const validator of validators) {
                const fieldResultArr = [];

                const errCode = validator(
                    result.hasOwnProperty(fieldName) ? result[fieldName] : value,
                    data,
                    fieldResultArr
                );

                if (errCode) {
                    errors[fieldName] = errCode;
                    break;
                } else if (fieldResultArr.length) {
                    result[fieldName] = fieldResultArr[0];
                } else if (data.hasOwnProperty(fieldName) && !result.hasOwnProperty(fieldName)) {
                    result[fieldName] = value;
                }
            }
        }

        if (util.isEmptyObject(errors)) {
            this.errors = null;
            return result;
        } else {
            this.errors = errors;
            return false;
        }
    }

    getErrors() {
        return this.errors;
    }

    registerRules(rules) {
        for (const ruleName in rules) {
            this.validatorBuilders[ruleName] = rules[ruleName];
        }

        return this;
    }

    registerAliasedRule(alias) {
        if (!alias.name) throw 'Alias name required';

        this.validatorBuilders[alias.name] = this.constructor._buildAliasedRule(
            alias.rules,
            alias.error
        );

        return this;
    }

    getRules() {
        return this.validatorBuilders;
    }

    _parseRule(livrRule) {
        let name;
        let args;

        if (util.isObject(livrRule)) {
            name = Object.keys(livrRule)[0];
            args = livrRule[name];

            if (!Array.isArray(args)) args = [args];
        } else {
            name = livrRule;
            args = [];
        }

        return { name, args };
    }

    _buildValidator(name, args) {
        if (!this.validatorBuilders[name]) {
            throw 'Rule [' + name + '] not registered';
        }

        const allArgs = [];

        allArgs.push.apply(allArgs, args);
        allArgs.push(this.getRules());

        return this.validatorBuilders[name].apply(null, allArgs);
    }

    _autoTrim(data) {
        const dataType = typeof data;

        if (dataType !== 'object' && data) {
            if (data.replace) {
                return data.replace(/^\s*/, '').replace(/\s*$/, '');
            } else {
                return data;
            }
        } else if (dataType == 'object' && Array.isArray(data)) {
            const trimmedData = [];

            for (const item of data) {
                trimmedData.push(this._autoTrim(item));
            }

            return trimmedData;
        } else if (dataType == 'object' && util.isObject(data)) {
            const trimmedData = {};

            for (const key in data) {
                if (data.hasOwnProperty(key)) {
                    trimmedData[key] = this._autoTrim(data[key]);
                }
            }

            return trimmedData;
        }

        return data;
    }
}

module.exports = Validator;


/***/ })

}]);