/*jslint white: true, browser: true, undef: true, nomen: true, eqeqeq: true,
plusplus: true, bitwise: true, newcap: true, immed: true, maxlen: 80 */
/*global jQuery, $*/

// This is a jQuery plugin for doing magstripe card processing.
(function ($) {

    // Plugin definition
    $.fn.magstripe = function (options) {

        // Build main options
        var opts = $.extend({}, $.fn.magstripe.defaults, options);
        var cardFormat = /\d{16}/;

        // Process each element
        return $(this).each(function () {

            var obj = $(this);

            // Use the meta plugin to build element specific options
            obj.o = $.meta ? $.extend({}, opts, obj.data()) : opts;

            obj.keydown(function (e) {
                if (e.keyCode === 13) {
                    e.preventDefault();
                }
            });

            obj.keyup(function (e) {
                if (e.keyCode === 13) {
                    e.preventDefault();
                }
            });

            // If focusNext functionality is enabled, 
            if (obj.o.focusNext === true) {
                obj.bind('keystrokes', {keys: ['enter']},
                    function (e) {
                        if (cardFormat.test($(this).val())) {
                            var thisIndex = $(":input:visible").index($(this));
                            var nextIndex = thisIndex + 1;
                            var nextSelector = ":input:visible:eq(" +
                                nextIndex + ")";
                            var nextInput = $(nextSelector);
                            nextInput.focus();
                        }
                        e.handled = true;
                    }
                );
            }

            // Key handlers that handle processing and validating the input from
            // the magstripe reader.
            if (obj.o.filterCardInput === true) {
                obj.keydown(function (event) {
                    if (event.keyCode === 13) {
                        var cardNumber = obj.val();
                        if (cardNumber.charAt(0) === ';' &&
                            cardNumber.charAt(20) === '?') {
                            cardNumber = cardNumber.substring(1, 17);
                            obj.val(cardNumber);
                        }
                        if (!cardFormat.test(cardNumber)) {
                            // Format error
                            obj.val("");
                            if (obj.o.errorElement !== '') {
                                $(obj.o.errorElement).html('Card read error.');
                            }
                        } else {
                            if (obj.o.errorElement !== '') {
                                $(obj.o.errorElement).html('');
                            }
                        }
                    }
                });
                obj.keypress(function (event) {
                    if (event.keyCode === 13) {
                        if (cardFormat.test(obj.val())) {
                            if (obj.o.submit === true) {
                                obj.parents('form:first').submit();
                            }
                        }
                    }
                });
            }

            // If focus functionality is enabled, select either the magstripe
            // field or the first input with an error.
            if (obj.o.focus === true) {
                var errorContainer = $(obj.o.fieldErrorSelector);
                if (errorContainer.length !== 0) {
                    var errorElement = $(errorContainer.find(':input'));
                    errorElement.select();
                } else {
                    obj.select();
                }
            }
  
        });
    };

    // Plugin defaults
    $.fn.magstripe.defaults = {
        filterCardInput: false,
        focus: false,
        focusNext: false,
        submit: false,
        errorElement: '',
        fieldErrorSelector: '.field-error:first'
    };

}(jQuery));
