/*
 * mtcNumberArrows - A jQuery plugin for arrows on an input field
 * Version : 0.1
 * Author : Lennox Norrie
 */

;(function ($, window, document, undefined) {

    "use strict";

    // Create the defaults once
    var plugin_name = 'mtcNumberArrows';

    // The actual plugin constructor
    function Plugin(element, options) {
        this.element = element;
        this.$this = $(this.element);
        this.defaults = {
            up_arrow: '<i class="fa fa-caret-up"></i>',
            down_arrow: '<i class="fa fa-caret-down"></i>'
        };
        this.settings = $.extend({}, this.defaults, options);
        this._defaults = this.defaults;
        this._name = plugin_name;

        this.init();
    }

    // Avoid Plugin.prototype conflicts
    $.extend(Plugin.prototype, {

        init: function () {
            // set some vars
            var plugin = this,
                $this = plugin.$this;

            plugin.addMarkup();

            plugin.addOrSubtract('add');
            plugin.addOrSubtract('subtract');

            plugin.outOfRange();

        },

        addMarkup: function () {
            // set some vars
            var plugin = this,
                number = plugin.$this;

            number.after('<div class="numberButtons"><div class="numberButton add">' +
                plugin.settings.up_arrow + '</div><div class="numberButton subtract">' +
                plugin.settings.down_arrow + '</div></div>');

            number.parents('.inputWrap').addClass('numberArrowWrap');

            if (number.val() <= plugin.getMinMax('min')) {
                number.parents('.inputWrap').find('.subtract').addClass('disabled');
            }

            if (number.val() >= plugin.getMinMax('max')) {
                number.parents('.inputWrap').find('.add').addClass('disabled');
            }
        },

        getMinMax: function(sum) {
            var plugin = this,
                input = plugin.$this;

            if (sum === 'min') {
                return ((input.data('min')) ? input.data('min') : 0);
            } else if (sum === 'max') {
                return ((input.data('max')) ? input.data('max') : Number.MAX_VALUE);
            }
        },

        addOrSubtract: function (operation) {
            // set some vars
            var plugin = this,
                number = plugin.$this;

            if (operation === 'subtract') {

                // subtract with down arrow
                number.siblings('.numberButtons').find('.subtract').on('click', function () {

                    var input = number,
                        count = input.val(),
                        min = plugin.getMinMax('min');

                    if (count > min) {
                        number.focus();
                        count--;
                        number.val(count);
                        number.change();
                    }
                });

            } else if (operation === 'add') {
                // add with up arrow
                number.siblings('.numberButtons').find('.add').on('click', function () {

                    var input = number,
                        count = input.val(),
                        max = plugin.getMinMax('max');

                    if (count < max) {
                        number.focus();
                        count++;
                        number.val(count);
                        number.change();
                    }
                });
            }

            number.on('change', function () {
                plugin.checkClass();
            });
        },

        checkClass: function () {
            // set some vars
            var plugin = this,
                number = plugin.$this,
                count = number.val();

            if (count > plugin.getMinMax('min')) {
                number.siblings('.numberButtons').find('.subtract').removeClass('disabled');
            } else {
                number.siblings('.numberButtons').find('.subtract').addClass('disabled');
            }

            if (count < plugin.getMinMax('max')) {
                number.siblings('.numberButtons').find('.add').removeClass('disabled');
            } else {
                number.siblings('.numberButtons').find('.add').addClass('disabled');
            }
        },

        outOfRange: function () {
            //set some vars
            var plugin = this,
                input = plugin.$this,
                value,
                min = plugin.getMinMax('min'),
                max = plugin.getMinMax('max');

            // set value of out of range
            input.on('keyup', function () {
                value = input.val();

                // check if value is lower than min allowed or isn't numeric
                if (value < min || !$.isNumeric(value) && value != '') {
                    input.val(min);
                    input.change();
                }

                // check if value is higher than max allowed
                if (value > max) {
                    input.val(max);
                    input.change();
                }
            });
        },

        runCallbackFunction: function (functionName) {
            // set some vars
            var plugin = this;
            // check if a function and run it
            if (typeof plugin.settings[functionName] === 'function') {
                plugin.settings[functionName]();
            }
        },

        destroy: function (mode) {
            // set some vars
            var plugin = this,
                $this = plugin.$this;

            // remove plugin data from trigger
            $this.removeData('plugin_' + plugin_name);

            //remove markup
            $('.numberButtons').remove();

            //take off the on click events
            $('.numberButtons').find('.subtract, .add').off('click');

            //removing wrapping class which adds padding
            $('.numberArrowWrap').removeClass('numberArrowWrap');

        }
    });

    // A really lightweight plugin wrapper around the constructor,
    // preventing against multiple instantiations
    $.fn[plugin_name] = function (options) {
        return this.each(function () {
            var plugin, _name;
            plugin = $.data(this, 'plugin_' + plugin_name);

            if (typeof options === 'string') {
                if (plugin !== null) {
                    if (typeof plugin[_name = options] === 'function') {
                        return plugin[_name]();
                    } else {
                        return void 0;
                    }
                } else {
                    return void 0;
                }
            } else if (!plugin) {
                $.data(this, 'plugin_' + plugin_name, new Plugin(this, options));
            }
        });
    };

}(jQuery, window, document));