(function ($) {

    //================================
    // fields
    //================================

    var inputSelector = "INPUT[data-role=rename]",
        config = {
            maxLength: 50,
            commitKeys: [13, 9],
            cancelKeys: [27],
            keyDown: null,
            keyPress: null,
            focus: null,
            blur: null,
            commit: null,
            cancel: null,
            error: null,
            css: {
                padding: "0px",
                height: "16px",
                width: "95%",
                border: "1px solid #CCCCCC;"
            }
        };

    //================================
    // main
    //================================

    $.fn.rename = function (method) {

        var result = null;

        if (METHODS[method]) {
            return METHODS[method].apply(this, Array.prototype.slice.call(arguments, 1));
        }
        else if (typeof method === 'object' || !method) {
            return METHODS.init.apply(this, arguments);
        }
        else {
            $.error('Method ' + method + ' does not exist on jQuery.dirtyForms');
        }

        return result;

    };

    //================================
    // methods
    //================================

    var METHODS = {

        init: function (options) {

            var oldValue = this.text(),
                input = null;

            config = $.extend(config, options);

            if (this.find(inputSelector).length > 0) {
                return this;
            }

            input = this.html("<input type=\"text\" data-role=\"rename\" style=\"color:#000000;\" />").find("[data-role=rename]").first();
            input.val(oldValue);
            input.css(config.css);
            input.enableTextSelection();
            input.select();
            input.focus();
            input.attr("maxLength", config.maxLength);

            input.on("blur", $.proxy(function (e) {

                e = $.extend({
                    newValue: input.val(),
                    oldValue: oldValue
                }, e);

                $.proxy(function () {
                    METHODS.commit.apply(this, [e]);
                }, this)();

            }, this));

            input.on("focus", $.proxy(function (e) {

                if ($.isFunction(config.focus)) {
                    config.focus(e);
                }

            }, this));

            input.on("keydown", $.proxy(function (e) {

                e = $.extend({
                    newValue: input.val(),
                    oldValue: oldValue
                }, e);

                if ($.inArray(e.keyCode, config.cancelKeys) > -1) {

                    e.preventDefault();

                    if ($.isFunction(config.cancel)) {
                        config.cancel(e);
                    }

                    this.html(e.oldValue);

                    return;

                }

                if ($.inArray(e.keyCode, config.commitKeys) > -1) {

                    e.preventDefault();

                    $.proxy(function () {
                        METHODS.commit.apply(this, [e]);
                    }, this)();

                }

            }, this));

            input.on("mousedown", $.proxy(function (e) {
                e.stopPropagation();
            }));

            if ($.isFunction(config.keyPress)) {
                input.on("keypress", $.proxy(config.keyPress));
            }

        },

        isLengthValid: function (e) {

            if (config.maxLength < e.newValue.length) {
                e.preventDefault();
                e.stopPropagation();
                return false;
            }

            return true;

        },

        commit: function (e) {

            if (e.newValue === "") {
                this.html(e.oldValue);
            }
            else {

                if ($.isFunction(config.commit)) {
                    config.commit(e);
                }

                this.html(e.newValue);
            
            }

        }

    };

})(jQuery);