﻿(function ($) {

    $.fn.tapvalidation = function (options) {
        var methods = {
            validateRequired: function (value) {
                return value && value != '' ? value.length > 0 : false;
            },
            validateCompare: function (rule, el, els) {
                if (els && els.length > 0) {
                    for (var i = 0; i < els.length; i++) {
                        if (els[i] != el) {
                            if (methods.getElValue(rule, el) != methods.getElValue(rule, els[i]))
                                return false;
                        }
                    }
                    return true;
                }
                else {
                    return false;
                }
            },
            bindRule: function (rule) {
                var elements = new Array();
                if (rule.element) {
                    elements.push(rule.element);
                }
                if (rule.elements) {
                    for (var i = 0; i < rule.elements.length; i++) {
                        if (rule.elements[i]) {
                            elements.push(rule.elements[i]);
                        }
                    }
                }

                for (var i = 0; i < elements.length; i++) {
                    var itemContext = { el: elements[i], els: elements, rule: rule };
                    var itemFunction = Function.createDelegate(itemContext, function (domEl) {
                        var context = this;
                        methods.validateRuleContext(context);
                    });
                    elements[i].bind('focus keyup blur click', itemFunction);
                }
            },
            validateRuleContext: function (context) { // context : {el, els, rule} ~ el - current element, els ~ other elements, rule ~ specified rule
                //var context = { el: elements[i], els: elements, rule: rule };
                var elValue = methods.getElValue(context.rule, context.el); //context.rule.valueGet ? context.rule.valueGet(context.el) : context.el.val();
                var validateResult = context.rule.validate ? context.rule.validate(context.rule) : true;
                var isRequiredResult = context.rule.isRequired ? methods.validateRequired(elValue) : true;
                var isCompareResult = context.rule.isCompare ? methods.validateCompare(context.rule, context.el, context.els) : true;
                if (validateResult && isRequiredResult && isCompareResult) {
                    context.el.removeClass(context.rule.invalidClass);
                    return true;
                }
                else {
                    context.el.addClass(context.rule.invalidClass);
                    return false;
                }
            },
            getElValue: function (rule, jEl) {
                return rule.valueGet ? rule.valueGet(jEl) : jEl.val();
            },
            checkRuleIsValid: function (rule) {
                var elements = new Array();
                if (rule.element) {
                    elements.push(rule.element);
                }
                if (rule.elements) {
                    for (var i = 0; i < rule.elements.length; i++) {
                        if (rule.elements[i]) {
                            elements.push(rule.elements[i]);
                        }
                    }
                }

                for (var i = 0; i < elements.length; i++) {
                    var context = { el: elements[i], els: elements, rule: rule };
                    return methods.validateRuleContext(context);
                }
            },
            validateOnSubmit: function () {
                var isValid = true;
                if (settings.rules != null && settings.rules.length > 0) {
                    for (var i = 0; i < settings.rules.length; i++) {
                        if (!methods.checkRuleIsValid(settings.rules[i])) {
                            isValid = false;
                            //TODO: to validate all elements & highlights their
                            //break;
                        }
                    }
                }
                if (isValid) {
                    if (settings.action)
                        settings.action();
                }
                return isValid;
            }
        };

        var settings = {
            'event': 'click',
            'action': null,
            'rules': null   // array of rules
        };

        // Rule fields
        /*
        {
        'element': jElement, // element to validation
        'elements': null, // elements array to validation
        'validate': null, // custom validation function
        'invalidClass': 'validation-error', // class which applied to element if it is not valid
        'isRequired': true, // flag which indicates that required field validation
        'valueGet': null, // method which gets value of element to checking required or compare(by default is val() function of jQuery)
        'isCompare': false // compares all elements values ~ val() function, from list
        }
        */

        return this.each(function () {
            var $this = $(this),
            data = $this.data('tapvalidation'),
            tapvalidation = 'tapvalidation_marker';

            // If options exist, lets merge them with our default settings
            if (options) {
                $.extend(settings, options);
            }

            // If the plugin hasn't been initialized yet
            if (!data) {

                // TapValidation plugin initialization code

                // add initialization marker to exclude reinitialization
                $this.data('tapvalidation', {
                    target: $this,
                    tapvalidation: tapvalidation
                });

                initialize($this);
            }

        });

        function initialize(submitEl) {
            submitEl.bind(settings.event, Function.createDelegate(submitEl, methods.validateOnSubmit));
            if (settings.rules != null && settings.rules.length > 0) {
                for (var i = 0; i < settings.rules.length; i++) {
                    methods.bindRule(settings.rules[i]);
                }
            }
        }

        function ValidateOnSubmit(submitEl) {
        }

    };
})(jQuery);
