/*
  backgrid-valid-min-max-cell 1.0.0
*/
(function (root, factory) {

    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['underscore', 'backgrid'], factory);
    } else if (typeof exports === 'object') {
        // CommonJS
        module.exports = factory(require('underscore'), require('backgrid'));
    } else {
        // Browser globals
        factory(root._, root.Backgrid);
    }

}(this, function (_, Backgrid) {

    //Fix require config issue with Underscore.
    if (!_)
        _ = this._;

    function MakeCellValidMinMax(cellView) {
        return cellView.extend({
            className: cellView.prototype.className + ' valid-min-max-cell',
            invalidMinMessage: function (value, limit, includeLimit) {
                return 'Minimum value reached: ' + limit.toString();
            },
            invalidMaxMessage: function (value, limit, includeLimit) {
                return 'Maximum value reached: ' + limit.toString();
            },
            minProp: null,
            maxProp: null,
            includeMin: true,
            includeMax: true,
            nullValid: true,

            initialize: function () {
                cellView.prototype.initialize.apply(this, arguments);

                this.listenTo(this.model, 'change:' + this.minProp + ' change:' + this.maxProp, this.model_change_limits);
            },
            render: function () {
                cellView.prototype.render.apply(this, arguments);

                this.update();

                return this;
            },
            update: function () {
                var value = this.model.get(this.column.get('name')),
                    min = this.model.get(this.minProp),
                    max = this.model.get(this.maxProp);

                if (this.validateMin(value, min, this.includeMin) == false) {
                    var invMsg = ($.isFunction(this.invalidMinMessage) == true)
                                    ? this.invalidMinMessage(value, min, this.includeMin)
                                    : this.invalidMinMessage;

                    this.$el.attr('title', invMsg)
                            .removeClass('max-reached')
                            .addClass('min-reached');
                }
                else if (this.validateMax(value, max, this.includeMax) == false) {
                    var invMsg = ($.isFunction(this.invalidMaxMessage) == true)
                                    ? this.invalidMaxMessage(value, max, this.includeMax)
                                    : this.invalidMaxMessage;

                    this.$el.attr('title', invMsg)
                            .removeClass('min-reached')
                            .addClass('max-reached');
                }
                else {
                    this.$el.attr('title', '')
                            .removeClass('min-reached')
                            .removeClass('max-reached');
                }
            },
            validateMin: function (value, limit, includeLimit) {
                if (limit != null) {
                    if (value != null) {
                        if (includeLimit == true)
                            return (value >= limit);
                        else
                            return (value > limit);
                    }
                    else {
                        return this.nullValid;
                    }
                }
                else {
                    return true;
                }
            },
            validateMax: function (value, limit, includeLimit) {
                if (limit != null) {
                    if (value != null) {
                        if (includeLimit == true)
                            return (value <= limit);
                        else
                            return (value < limit);
                    }
                    else {
                        return this.nullValid;
                    }
                }
                else {
                    return true;
                }
            },

            model_change_limits: function (model, value, opt) {
                try {
                    this.update();
                }
                catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); };
            },
        });
    };

    Backgrid.Extension.MakeCellValidMinMax = MakeCellValidMinMax;
}));
