﻿(function ($, window, document, undefined) {

    var kendo = window.kendo,
    binders = kendo.data.binders,
    Binder = kendo.data.Binder,
    toString = kendo.toString;

    var parsers = {
        "number": function (value) {
            return kendo.parseFloat(value);
        },

        "date": function (value) {
            return kendo.parseDate(value);
        },

        "boolean": function (value) {
            if (typeof value === "string") {
                return value.toLowerCase() === "true";
            }
            return value != null ? !!value : value;
        },

        "string": function (value) {
            return value != null ? (value + "") : value;
        },

        "default": function (value) {
            return value;
        }
    };

    function modelValidationRefreshFunction() {
        //If validation is already bound - don't recall
        var $this = $(this.element);
        if ($this.data("kendoValidator")) return;

        var value = this.bindings["modelValidator"];
        var paths = value.path.split('.');

        //last item is schema field. before that everything is property in model
        var rootObject = "";
        if (paths.length > 1) {
            rootObject = value.source[paths[0]];
        } else {
            rootObject = value.source;

        }


        for (var i = 1, len = paths.length - 2; i < len; i++) {
            rootObject = rootObject[paths[i]];
        }

        if (!rootObject || !rootObject.fields) return;

        var field = rootObject.fields[paths[paths.length - 1]];
        if (!field) {
            throw new Error("Wrong field name:" + value.path);
        }

        if (!field.validation && field.type != "string") {
            return;
        }else{
            if(!field.validation){
                field.validation = {};
            }
        }

        var isFunction = kendo.isFunction,
            isPlainObject = $.isPlainObject,
            validation = field ? field.validation : {},
            rule,
            attr = {},
            rules = {};

        // Input validation as a part of PCI changes
        if(field.type == "string"){
            if(validation){
                if(!validation.pattern){
                    validation.pattern = { 
                        value: "^[a-zA-Z0-9!@ \$%\*\[|\\]\+=_;\/\\\\\?:,()#&/'‘’.\s-]*$",
                        message: "Input can contain letters, numbers, spaces, and the characters ! @ $ % * [ ] + = _ ; / ? : , ( ) # & &#92; ' . -"
                    };
                }
            }
        }
        
        for (var ruleName in validation) {
            rule = validation[ruleName];

            /*known validations and other html attributes*/
            if (!isFunction(rule)) {
                var ruleValue = isPlainObject(rule) ? (rule.hasOwnProperty("value") ? rule.value : ruleName) : rule;
                attr[ruleName] = ruleValue;
                if (ruleName === "min" || ruleName === "max") {
                    var numBox = $this.data("kendoNumericTextBox");
                    if (numBox) {
                        numBox[ruleName](ruleValue);
                    }
                }
            }
            
            if (rule.message) attr[kendo.attr(ruleName + "-msg")] = rule.message;

            /*custom validations*/
            if (isPlainObject(rule) && rule.value) {
                rule = rule.value;
            }

            if (isFunction(rule)) {
                rules[ruleName] = rule;
            }
        }

        if($(this.element)[0].type == "textarea"){
            rules[ruleName] = function(item) {
                var re = "^[a-zA-Z0-9\\n!@ \$%\*\[|\\]\+=_;\/\\\\\?:,()#&/'‘’.\s-]*$";
                return item.val().match(re);
            };
        }
        
        var validator = new kendo.ui.Validator(this.element, {
            //validateOnBlur: false,
            //errorTemplate: that.options.errorTemplate || undefined,
            rules: rules
        });
        
        $this.attr(attr);

        var source = value.source;
        var modelValidators = null;
        if (!source.modelValidators) {
            var parents = value.parents;
            for (var i = 0, len = parents.length; i < len; i++) {
                if (parents[i] && parents[i].modelValidators) {
                    modelValidators = parents[i].modelValidators;
                    break;
                }
            }
            if (modelValidators == null) {
                source.modelValidators = new Array();
                modelValidators = source.modelValidators;
            }
        } else {
            modelValidators = source.modelValidators;
        }

        modelValidators.push(validator);
    };

    binders.widget.modelValidator = Binder.extend({
        init: function (widget, bindings, options) {
            //call the base constructor
            Binder.fn.init.call(this, widget.element[0], bindings, options);
        },
        refresh: modelValidationRefreshFunction
    });

    binders.modelValidator = Binder.extend({
        
        refresh: modelValidationRefreshFunction
    });

    binders.widget.minDate = Binder.extend({
        init: function (widget, bindings, options) {
            Binder.fn.init.call(this, widget.element[0], bindings, options);
        },
        refresh: function () {
            var currentDate = this.bindings["value"].get();
            var minDate = this.bindings["minDate"].get();
            if (!minDate) return;

            //Minimum date should be at least one day more.
            var datePicker = $(this.element).data("kendoDatePicker");
            datePicker.min(minDate);

            if (currentDate && currentDate < minDate) {
                this.bindings["value"].set(minDate);
            }
        }
    });


    binders.widget.windowController = Binder.extend({
        init: function (widget, bindings, options) {
            Binder.fn.init.call(this, widget.element[0], bindings, options);
        },
        refresh: function () {
            var binding = this.bindings["windowController"];
            binding.source.windowController = $(this.element).data("kendoWindow");
        }
    });

    binders.widget.defaultFocus = Binder.extend({
        init: function (widget, bindings, options) {
            Binder.fn.init.call(this, widget.element[0], bindings, options);


            if (widget instanceof kendo.ui.Grid) {
                this.elementToWork = widget.table;
            } else if (widget.input) {
                this.elementToWork = widget.input;
            }
            else {
                this.elementToWork = this.element;
            }
            this.checkRefresh(this);
        },
        checkRefresh: function (that) {
            if (!that.elementToWork.getBoundingClientRect) {
                that.elementToWork.focus();
                return;
            }

            var rect = that.elementToWork.getBoundingClientRect();
            if (rect.top > 0 || rect.left > 0) {
                that.elementToWork.focus();
            } else {
                return;
                setTimeout(
                    function () {
                        that.checkRefresh(that);
                    }, 500);
            }
        },
        refresh: function () {
            this.checkRefresh(this);
        }
    });

    binders.defaultFocus = Binder.extend({
        init: function (element, bindings, options) {
            Binder.fn.init.call(this, element, bindings, options);
            this.elementToWork = this.element;
            this.checkRefresh(this);
        },
        checkRefresh: function (that) {
            var rect = that.elementToWork.getBoundingClientRect();
            if (rect.top > 0 || rect.left > 0) {
                that.elementToWork.focus();
            } else {
                setTimeout(
                    function () {
                        that.checkRefresh(that);
                    }, 500);
            }
        },
        refresh: function () {
            this.checkRefresh(this);
        }
    });
    
    binders.formattedText = Binder.extend({
        init: function (element, bindings, options) {
            //call the base constructor
            Binder.fn.init.call(this, element, bindings, options);
            this.jelement = $(element);
            this.format = this.jelement.attr("data-format");
            this.culture = this.jelement.attr("data-culture") || "en-IN";
            this.parser = parsers[this.jelement.attr("data-parser") || "default"];
        },
        refresh: function () {
            var text = this.bindings.formattedText.get();
            if (text === null) {
                text = "";
            }
            else if (this.format) {
                text = toString(this.parser(text), this.format, this.culture);
            }
            this.jelement.text(text);
        }
    });

    binders.widget.firstRowSelect = Binder.extend({
        init: function (widget, bindings, options) {
            Binder.fn.init.call(this, widget.element[0], bindings, options);
            this.grid = $(this.element).data("kendoGrid");

            var that = this;
            that.grid.bind("dataBound", function () {
                that.grid.select(jQuery("tr:eq(0)", that.grid.tbody));
            });
        },
        refresh: function () {
        }
    });

    binders.widget.selectedAccessKey = Binder.extend({
        init: function (widget, bindings, options) {
            Binder.fn.init.call(this, widget.element[0], bindings, options);

            // http://jsfiddle.net/rgullhaug/QWwnR/

            var that = this;
            $(this.element).data("kendoGrid").bind("change", function (e) {
                // Get the selected DOM elements as jQuery objects.
                var $selectedElements = e.sender.select();

                if (that._selectedElements) {
                    jQuery("[selectedaccesskey]", that._selectedElements).removeAttr("accesskey");
                }

                that._selectedElements = $selectedElements;

                jQuery("[selectedaccesskey]", that._selectedElements).each(function () {
                    var $this = jQuery(this);
                    $this.attr("accesskey", $this.attr("selectedaccesskey"));
                });
            });
        },
        refresh: function () {

        }
    });

    binders.widget.autoRowSelect = Binder.extend({
        init: function (widget, bindings, options) {
            Binder.fn.init.call(this, widget.element[0], bindings, options);

            var that = this;
            var arrows = [38, 40];
            var grid = $(this.element).data("kendoGrid");
            grid.table.bind("keydown", function (e) {

                if (arrows.indexOf(e.keyCode) >= 0) {
                    setTimeout(function () {
                        grid.select($(".k-state-focused", grid.table).closest("tr"));
                    });
                }
            });
        },
        refresh: function () {

        }
    });

})(jQuery, window, document);