(function($){
    $.widget("ui.cdkey", {
        options: {
            maxlen: 4,
            segcnt: 6
        },
        _create: function() {
            var $element = this.element;
            var $options = this.options;
            var $parent = this.element.parent();
            var $preval = this.element.val();
            if ($preval) {
                var cdkey_value = $preval.split('-');
            } else {
                var cdkey_value = new Array(this.options.segcnt);
                for (var i = 0; i < this.options.segcnt; i++) {
                    cdkey_value[i] = "";
                }
            }
            var cdkey_parts = [];
            var id_prefix = this.element.attr('name').replace(/\[/g, '_').replace(/\]/g, '');
            for (var i = 0; i < this.options.segcnt; i++) {
                cdkey_parts.push('<input type="text" class="ui-form-cdkey-part ui-widget-content" index="' + i + '" id="' + id_prefix + '_cdkey_' + i + '" value="' + cdkey_value[i] + '" />');
            }
            var cdkey_html = cdkey_parts.join('-');
            this.element.after($('<div class="ui-form-cdkey-container" style="display: inline' + (($.browser.msie) ? '' : '-block') + ';"/>').html(cdkey_html));
            var isValidKey = function(e) {
                var valid = [
                    8,        // backspace
                    9,        // tab
                    13,       // enter
                    27,       // escape
                    35,       // end
                    36,       // home
                    37,       // left arrow
                    39,       // right arrow
                    46,       // delete
                    109, 189  // connector
                ];
                if ((e.keyCode >= 65 && e.keyCode <= 90) || (e.keyCode >= 48 && e.keyCode <= 57 && !e.shiftKey) || (e.keyCode >= 96 && e.keyCode <= 105))
                    return true;
                // only allow shift key with tab
                if (e.shiftKey && e.keyCode != 9)
                    return false;
                for (var i = 0; i < valid.length; i++) {
                    if (e.keyCode == valid[i])
                        return true;
                }
                return false;
            };
            $('input.ui-form-cdkey-part', $parent).bind('paste', function(e) {
                var ele = $(this);
                var idx = ele.attr('index');
                setTimeout(function() {
                    var temp_cdkey_value = $(ele).val();
                    var vals = temp_cdkey_value.split('-');
                    $('input.ui-form-cdkey-part', $parent).each(function(i) {
                        if (i >= idx) {
                            if (vals.length > i - idx)
                                $(this).val(vals[i - idx].substr(0,4));
                        }
                    });
                }, 0);
            }).bind('keydown', function(e) {
                if (!isValidKey(e)) return false;
                var next_cdkey_part = $(this).next('input.ui-form-cdkey-part', $parent);
                var prev_cdkey_part = $(this).prev('input.ui-form-cdkey-part', $parent);
                // jump to next cdkey part on connector
                if (e.keyCode == 109 || e.keyCode == 189) {
                    if (next_cdkey_part.length) {
                        $(this).trigger('blur');
                        next_cdkey_part.focus();
                    }
                    return false;
                }
                if (($(this).caret()[1] - $(this).caret()[0])) {
                    return true;
                }
                // jump to next cdkey part if maxlength is reached and number key or right arrow is pressed
                if ((this.value.length == $options.maxlen  && (e.keyCode != 8 && e.keyCode != 37 && e.keyCode != 39)) || (e.keyCode == 39 && $(this).caret()[0] == this.value.length)) {
                    if (next_cdkey_part.length) {
                        $(this).trigger('blur');
                        next_cdkey_part.focus().caret(0);
                        return false;
                    }
                    return false;
                }
                // jump to previous cdkey part if left arrow is pressed and caret is at the 0 position
                if (e.keyCode == 37 && $(this).caret()[0] == 0) {
                    if (prev_cdkey_part.length) {
                        $(this).trigger('blur');
                        prev_cdkey_part.caret(prev_cdkey_part.val().length);
                        return false;
                    }
                }
                // jump to previous cdkey part on backspace
                if (e.keyCode == 8 && $(this).caret()[0] == 0 && $(this).caret()[0] == $(this).caret()[1]) {
                    if (prev_cdkey_part.length) {
                        $(this).trigger('blur');
                        prev_cdkey_part.focus().caret(prev_cdkey_part.val().length);
                        return false;
                    }
                }
            });
        },
        destroy: function() {
            $.Widget.prototype.destroy.call(this);
        },
        value: function() {
            var cdkey_value = [];
            $('input.ui-form-cdkey-part', this.element.parent()).each(function() {
                cdkey_value.push(this.value);
            });
            return cdkey_value.join('-');
        },
        clear: function() {
            $('input.ui-form-cdkey-part', this.element.parent()).val('');
            this.element.val('');
        },
        widget: function() {
            return this.element;
        }
    });
    $.extend($.ui.cdkey, {});
})(jQuery);