﻿(function($) {
    $.fn.InlineEdit = function(options) {
        // Set the options.
        var opts = $.extend({}, $.fn.InlineEdit.defaults, options);

        // Go through the matched elements and return the jQuery object.
        return this.each(function() {
            // Extend our options object with metadata from the DOM
            var o = $.metadata ? $.extend({}, opts, $(this).metadata()) : opts;
            var isRunning = false;

            var editField = $(this);
            var editForm = $('<form/>').addClass(o.formClass);
            var inputElm, saveElm, cancelElm;

            var ajaxLoad = $('<i id="inline-saving-message">Saving...</i>');

            var magicPadding;
            if ($.browser.mozilla || $.browser.safari)
                magicPadding = 1;
            else if ($.browser.msie)
                magicPadding = 2;

            editField.click(function(ev) {
                if (!isRunning) {
                    getValue();
                }
            }).hover(hoverIn, hoverOut);

            function getValue() {
                isRunning = true;
                editForm.empty();

                $.ajax({
                    type: 'get',
                    url: o.url + "/" + o.params.id,
                    data: $.extend({ date: new Date().getTime() }, { field: o.params.field }),
                    dataType: 'json',
                    success: function(viewModel) {
                        if (!viewModel.Success) {
                            ShowServiceMessages(viewModel);
                        } else {
                            getExtraData(viewModel.Result);
                        }
                    },
                    error: function() {
                    }
                });
            }

            function getExtraData(data) {
                if (o.extraDataUrl != null) {
                    $.ajax({
                        type: 'get',
                        url: o.extraDataUrl,
                        dataType: 'json',
                        success: function(viewModel) {
                            if (!viewModel.Success) {
                                ShowServiceMessages(viewModel);
                            } else {
                                buildEditForm(data, viewModel.Result);
                            }
                        },
                        error: function() {
                        }
                    });
                }
                else {
                    buildEditForm(data, null);
                }
            }

            function buildEditForm(data, extraData) {
                saveElm = $(buildButton('Save', 'small')).click(saveEdit);
                cancelElm = $(buildButton('Cancel', 'small')).click(cancelEdit);
                buildInputField();

                editForm.append(inputElm).append(o.formatExtraData.call(this, data, extraData)).append(saveElm).append(cancelElm);

                editFormShow(data);
            }

            function editFormShow(data) {
                var offset = editField.offset();

                editForm.css({
                    top: offset.top + (trimPx(editField.css('padding-top')) - (o.inputPadding + magicPadding)) - o.formPadding - o.inputBorder,
                    left: offset.left + (trimPx(editField.css('padding-left')) - (o.inputPadding + 1)) - o.formPadding - o.inputBorder,
                    width: editField.width() + o.formPadding + o.inputPadding + (o.inputBorder * 4),
                    padding: o.formPadding
                }).show();

                editForm.appendTo(document.body);

                if ($('.empty-field', editField).length == 0) {
                    inputElm.val(data);
                }

                inputElm.focus();

                o.onShow.call(editForm);
                isRunning = false;                
            }

            function buildInputField() {
                inputElm = $('<textarea class="inline-edit-input" />').css({
                    width: editField.width() + o.inputPadding + (o.inputBorder * 2),
                    height: (o.multiLine && (editField.innerHeight() < o.multiLineHeight)) ? o.multiLineHeight : editField.innerHeight() - (trimPx(editField.css('padding-top')) + trimPx(editField.css('padding-bottom'))),
                    'font-size': editField.css('font-size'),
                    'font-weight': editField.css('font-weight'),
                    'font-family': editField.css('font-family'),
                    'overflow': (o.multiLine) ? 'visible' : 'hidden',
                    padding: o.inputPadding,
                    'border': 'solid ' + o.inputBorder + 'px #1A85C6',
                    margin: 0
                }).bind(($.browser.opera ? 'keypress' : 'keydown'), function(ev) {
                    switch (ev.keyCode) {
                        case Key.Tab:
                        case Key.Return:
                            {
                                if (o.multiLine || !o.returnSubmit)
                                    return true;
                                saveEdit(ev);
                                break;
                            }
                        case Key.Esc:
                            {
                                cancelEdit(ev);
                                break;
                            }
                    }
                });
            }

            // Events.
            function hoverIn(ev) {
                editField.addClass('inline-edit-hover');
            }
            function hoverOut(ev) {
                editField.removeClass('inline-edit-hover');
            }
            function cancelEdit(ev) {
                o.onHide.call();
                editForm.hide();
                hoverOut();
                ev.preventDefault();
            }
            function saveEdit(ev) {
                editForm.append(ajaxLoad);
                $.ajax({
                    type: 'post',
                    url: o.url + "/" + o.params.id,
                    data: $.extend({ value: $.trim(inputElm.val()) }, { field: o.params.field }),
                    dataType: 'json',
                    success: function(viewModel) {
                        ShowServiceMessages(viewModel);

                        if (viewModel.Success) {
                            ajaxLoad.remove();
                            editField.append(o.formatSavedData.call(editField, viewModel.Result));
                            o.onHide.call();
                            editForm.hide();
                            hoverOut();
                        }
                        else {
                            var message = "";
                            $.each(viewModel.ServiceMessages, function(index, serviceMessage) {
                                message += serviceMessage.Message + " ";
                            });
                            $("#inline-saving-message").replaceWith(message);
                        }
                    },
                    error: function() {
                        ajaxLoad.remove();
                    }
                });
                ev.preventDefault();
            }
        });
    };
    // Public defaults.
    $.fn.InlineEdit.defaults = {
        url: null,
        extraDataUrl: null,
        onShow: function() { },
        onHide: function() { },
        formatSavedData: formatSavedData,
        formatExtraData: formatExtraData,
        formClass: 'inline-edit-form',
        multiLine: false,
        multiLineHeight: 100,
        formPadding: 10,
        inputPadding: 5,
        inputBorder: 1,
        returnSubmit: true
    };
    // Global Varialbles
    var Key = {
        Up: 38,
        Down: 40,
        Del: 46,
        Tab: 9,
        Return: 13,
        Esc: 27,
        Comma: 188,
        PageUp: 33,
        PageDown: 34,
        BackSpace: 8
    };
    // Private functions.
    function trimPx(value) {
        // remove "px" from values
        var pos = value.indexOf("px");
        if (pos != 0)
            return parseInt(value.substring(0, pos));
        else
            return 0;
    }

    function buildButton(value, size) {
        return '<div class="input-button ' + size + '"><input class="button-a" type="submit" value="' + value + '" title="' + value + '"/><div class="button-rh"><div class="button-r"></div></div></div>';
    }

    function formatSavedData(data) {
        // Default functionality is to render the data as text
        this.text(data);
    }

    function formatExtraData(data, extraData) {
        return extraData;
    }

})(jQuery);
