(function($){ 

$.widget("ui.editGrid", {  

    // Defaults
    /*
     * add, edit, remove, and save actions/options can be specified as boolean (false - disable), string (url - '/person/add'), 
     * or function (override default functionaility)
     */
    options: {
        width: 650,
        height: 400,
        pager: null,

        dialogOptions: { 
            autoOpen: true,
            modal: true
        },

        baseUrl: null, // ex. /user

        dataUrl: null, // ex. /user/grid
        add: true,
        edit: true,
        del: true,
        save: true,

        buttons: [
            // {
            //     text: "Test",
            //     icon: "ui-icon-mail-closed",
            //     click: function(id) { alert('clicked'); }
            // }
        ],

        loading: '<img src="/content/images/loading.gif" />',
        valid: function (form) { 
            return $(form).valid();
        }
    },

    _create: function() {
        var self = this;
        var opts = self.options;
        var $grid = $(self.element);

        var gridId = $grid.attr('id');
        var addButtonId = gridId + "_addButton";
        var editButtonId = gridId + "_editButton";
        var delButtonId = gridId + "_delButton";

        if (opts.pager) {
            this.pagerId = opts.pager.replace('#', '');
        } else {
            // No pager specified, create it
            this.pagerId = gridId + 'Pager';
            var $pager = $('<div />')
                .attr('id', this.pagerId)
                .insertAfter($grid);
        }

        var url = (opts.dataUrl != null) ? opts.dataUrl : opts.baseUrl + "/grid";

        $grid.jqGrid({
            url: url,
            colNames: opts.colNames,
            colModel: opts.colModel,
            gridComplete: function() {
                $('#' + addButtonId).show();
                $('#' + editButtonId).hide();
                $('#' + delButtonId).hide();
            },
            onCellSelect: function(rowid, iCol, cellcontent, e) {
                // console.log("onCellSelect", rowid, iCol, cellcontent, e);
            },
            onSelectRow: function(rowid, status) {
                $('#' + editButtonId).show();
                $('#' + delButtonId).show();
            },
            ondblClickRow: function(rowid, iRow, iCol, e) {
                self.edit(rowid);
            },
            altRows: true,
            pager: '#' + this.pagerId,
            width: opts.width,
            height: opts.height
        });
        
        $grid.navGrid('#' + this.pagerId, {
            add: false,
            edit: false,
            del: false,
            search: false
        });
        
        // Always destroy dialog as html content could contain overlapping id attributes on elements
        $.extend(this.options.dialogOptions, {
            close: function(e, ui) {
                $(this).dialog('destory').remove();
            }
        });

        self._initAdd();
        self._initButton(self.options.add, addButtonId, "Add ", "ui-icon-plus", function(id) { self.add(id) });

        self._initEdit();
        self._initButton(self.options.edit, editButtonId, "Edit ", "ui-icon-wrench", function(id) { self.edit(id) });

        self._initDel();
        self._initButton(self.options.del, delButtonId, "Delete ", "ui-icon-trash", function(id) { self.del(id) });
        
        self._initSave();

        // Add extra buttons
        var buttons = self.options.buttons;
        for (var i = 0; i < buttons.length; i++) {
            var button = buttons[i];

            var text = button.text + " ";
            var buttonId = gridId + "_" + text + "Button";
            var icon = button.icon;

            self._initButton(true, buttonId, text, icon, function(id) { button.click(id) });
            // TODO: Show by default, or only with selection
            $('#' + buttonId).show();
        }
    }, 

    destroy: function() {  
        // Seems slow to destroy grid when embedded, disabling for now
        // $(this.element).GridDestroy();
    }, 

    _setOption: function(option, value) {  
        $.Widget.prototype._setOption.apply(this, arguments);
      
        var el = this.element;
      
        //switch (option) {  
            //case "location":  
                //(value === "top") ? cap.css("top", el.offset().top) : cap.css("top", el.offset().top + el.height() - capHeight);  
                //break;  
            //case "color":  
                //el.next().css("color", value);  
                //break;  
            //case "backgroundColor":  
                //el.next().css("backgroundColor", value);  
                //break;  
        //}  
    },

    _initOption: function(option, defaultFunc) {
        if (option === true || typeof option === "string") {

            if (option === true && this.options.baseUrl == null) {
                throw "baseUrl option not specified";
            }

            // 'true' or 'string/url' specified
            return defaultFunc;

        } else if (typeof option === "function") {
            // Function/callable specified 
            return option;
        } else {
            return function(id) {} // Do nothing
        }
    },

    _initButton: function(option, buttonId, text, icon, clickHandler) {
        if (option) {
            var $grid = $(this.element);
            $grid.navButtonAdd('#' + this.pagerId, {
                id: buttonId,
                caption: text, 
                buttonicon: icon, 
                onClickButton: function(e) { 
                    var rowid = $grid.jqGrid('getGridParam', 'selrow');
                    clickHandler(rowid);
                }
            });
        }
        $('#' + buttonId).hide();
    },

    _initAdd: function() {
        this.add = this._initOption(this.options.add, function(id) {
            var url = (typeof this.options.add === "string")
                        ? this.options.add
                        : this.options.baseUrl + "/add"    

            var self = this;

            var dialogOptions = {
                title: 'Add ' + this.options.description,
                buttons: {
                    'Add': function () {
                        $('form', this).submit();
                    }
                }
            };
            $.extend(dialogOptions, this.options.dialogOptions);

            var $dialog = $('<div />')
                .appendTo('body')
                .html(self.options.loading)
                .load(url, function() {
                    $('form', this).submit(function() {
                        self.save(this);
                        return false;
                    });

                    $(this)
                        .initialize()
                        .find('input')
                        .keyup(function(e) {
                            if (e.keyCode == '13') {
                                $('form', this).submit();
                                return false;
                            }
                        });
                })
                .dialog(dialogOptions);
        });
    },

    _initEdit: function() {
        this.edit = this._initOption(this.options.edit, function(id) {
            var url = (typeof this.options.edit === "string")
                        ? this.options.edit
                        : this.options.baseUrl + "/edit"    

            var self = this;

            var dialogOptions = {
                title: 'Edit ' + this.options.description,
                buttons: {
                    'Save': function () {
                        $('form', this).submit();
                    }
                }
            };
            $.extend(dialogOptions, this.options.dialogOptions);

            var $dialog = $('<div />')
                .appendTo('body')
                .html(self.options.loading)
                .load(url + '?id=' + id, function() {
                    $('form', this).submit(function() {
                        self.save(this);
                        return false;
                    });

                    $(this)
                        .initialize()
                        .find('input')
                        .keyup(function(e) {
                            if (e.keyCode == '13') {
                                $('form', this).submit();
                                return false;
                            }
                        });
                })
                .dialog(dialogOptions);
        });
    },

    _initDel: function() {
        this.del = this._initOption(this.options.del, function(id) {
            var url = (typeof this.options.del === "string")
                        ? this.options.del
                        : this.options.baseUrl + "/delete"

            var self = this;
            var $grid = $(this.element);

            // var $message = $('<span>')
            //                     .html('Are you sure you want to delete the ' + this.options.description + '?')
            //                     .state({level: "highlight"});

            var dialogOptions = {
                title: 'Delete ' + this.options.description,
                buttons: {
                    'Delete': function () {

                        var $dialog = $(this).closest('.ui-dialog');
                        var $dialogContent = $(this);

                        block($dialog, 'Deleting ' + self.options.description);
                        $.post(url, { id: id }, function() {
                            unblock($dialog);
                            $dialogContent.dialog('close');
                            $grid.trigger('reloadGrid');
                        }); 
                        
                    },
                    'Cancel': function () {
                        $dialog = $(this);
                        $dialog.dialog('close');
                    }
                }
            };
            $.extend(dialogOptions, this.options.dialogOptions);

            var $dialog = $('<div />')
                .appendTo('body')
                .html('Are you sure you want to delete the ' + this.options.description + '?')
                // .state({level: "highlight"})
                .dialog(dialogOptions);
        });
    },

    _initSave: function() {
        this.save = this._initOption(this.options.save, function(form) {
            if (!this.options.valid(form)) {
                return false;
            }

            var url = (typeof this.options.save === "string")
                        ? this.options.save
                        : this.options.baseUrl + "/save"

            var $grid = $(this.element);
            var $dialog = $(form).closest('.ui-dialog');
            var $dialogContent = $(form).closest('.ui-dialog-content');

            var data = $(form).serialize();
            block($dialog, 'Saving ' + this.options.description);
            $.post(url, data, function(data) {
                unblock($dialog);
                $dialogContent.dialog('close');
                $grid.trigger('reloadGrid');
            }); 
        });
    }
  
});

})(jQuery);

