/*
Aqui ficam alguns códigos que resolvem certos bugs conhecidos do PrimeFaces na versão atual
e que não existe prazo definido para serem resolvidos oficialmente.

Se a versão do PrimeFaces for trocada algum dia, será preciso rever todas estas funcionalidades.

Todos os códigos abaixo foram verificados com a versão do primefaces 5.1 e as correções não foram feitas
Portanto, o código abaixo deve ser mantido até que a solução oficial seja feita

As linhas de código marcadas com (*) ou com algum tipo de comentário foram adicionadas/alteradas do código original
As linhas de código comentadas foram removidas do código original
*/

// Não funciona quando o datatable possui pe:inputNumber (em geral, campos múltiplos)
// Esta funcionalidade foi inicialmente implementada para resolver problemas no requerimento de remuneração, ao preencher os valores das remunerações
PrimeFaces.widget.DataTable.prototype.showCellEditor = function(g) {
    this.incellClick = true;
    var k = null,
    h = this;
    if(g) {
        k = g;
        if(this.contextMenuCell) {
            this.contextMenuCell.parent().removeClass("ui-state-highlight")
        }
    } else {
        k = this.contextMenuCell
    }
    
    if(this.currentCell) {
        h.saveCell(this.currentCell)
    }
    
    this.currentCell = k;
    var b = k.children("div.ui-cell-editor"),
    a = b.children("div.ui-cell-editor-output"),
    l = b.children("div.ui-cell-editor-input"),
    e = l.find(":input:enabled"),
    f = e.length > 1;
    k.addClass("ui-state-highlight ui-cell-editing");

    // temporary quick fix
	// só foi acrescentada a linha abaixo ao código original para sobreescrever a linha anterior
    f = false;

    a.hide();
    l.show();
    e.eq(0).focus().select();
    if(f) {
        var j = [];
        for(var d = 0; d < e.length; d++) {
            j.push(e.eq(d).val())
        }
        k.data("multi-edit", true);
        k.data("old-value", j)
    } else {
        k.data("multi-edit", false);
        k.data("old-value", e.eq(0).val())
    }
    if(!k.data("edit-events-bound")) {
        k.data("edit-events-bound", true);
        e.on("keydown.datatable-cell", function(o) {
            var n = $.ui.keyCode,
            i = o.which,
            m = o.shiftKey || i === n.UP,
            c = $(this);
            // este bloco abaixo foi completamente refatorado para resolver alguns bugs como também acrescentar funcionalidade do ENTER,UP,DOWN
            if (i === n.ENTER || i == n.NUMPAD_ENTER || i === n.DOWN || i === n.UP) {
                h.saveCell(k);
            	// esse bloco IF/ELSE inteiro foi adicionado
                if (f) {
                    var p = m ? c.index() - 1 : c.index() + 1;

                    if (p < 0 || (p === e.length)) {
                        h.enterCell(k, !m);
                    } else {
                        e.eq(p).focus();
                    }
                } else {
                    h.enterCell(k, !m);
                }
                o.preventDefault();
            } else if (i === n.TAB) {
                h.saveCell(k);	// (*)
                if(f) {
                    var p = m ? c.index() - 1 : c.index() + 1;

                    if(p < 0 || (p === e.length)) {
                        h.tabCell(k, !m);
                    } else {
                        e.eq(p).focus();
                    }
                } else {
                    h.tabCell(k, !m);
                }
                o.preventDefault();
            }
        }).on("focus.datatable-cell click.datatable-cell", function(c) {
            h.currentCell = k;
        });
    }        
};

// Resolvido problema com TAB quando apenas algumas colunas do datatable são editáveis
PrimeFaces.widget.DataTable.prototype.tabCell = function(a, d) {
    var b = d ? a.nextUntil("", "td.ui-editable-column") : a.prevUntil("", "td.ui-editable-column");
    if (b.length == 0) {
        var c = d ? a.parent().next() : a.parent().prev();
        b = d ? c.children("td.ui-editable-column:first") : c.children("td.ui-editable-column:last");
    }
    this.showCellEditor(b)
};

// Adicionada navegação com ENTER, UP e DOWN
PrimeFaces.widget.DataTable.prototype.enterCell = function(a, d) {
    var b = (d ? a.parent().next() : a.parent().prev()).children("td").eq(a.index());
    if (b.length == 0) {
        var c = (d ? a.parent().siblings().first() : a.parent().siblings().last()).children("td").eq(a.index());
        b = d ? c.nextUntil("", "td.ui-editable-column") : c.prevUntil("", "td.ui-editable-column");
    }
    this.showCellEditor(b)
};

PrimeFaces.widget.DataTable.prototype.bindEditEvents = function() {
    var c = this;
    this.cfg.cellSeparator = this.cfg.cellSeparator || " ";
    if (this.cfg.editMode === "row") {
        var a = "> tr > td > div.ui-row-editor";
        this.tbody.off("click.datatable", a).on("click.datatable", a, null, function(f) {
            var d = $(f.target),
                g = d.closest("tr");
            if (d.hasClass("ui-icon-pencil")) {
                c.switchToRowEdit(g);
                d.hide().siblings().show()
            } else {
                if (d.hasClass("ui-icon-check")) {
                    c.saveRowEdit(g)
                } else {
                    if (d.hasClass("ui-icon-close")) {
                        c.cancelRowEdit(g)
                    }
                }
            }
        })
    } else {
        if (this.cfg.editMode === "cell") {
            var b = "> tr > td.ui-editable-column";
            this.tbody.off("click.datatable-cell", b).on("click.datatable-cell", b, null, function(f) {	// executa ao CLICAR em um campo editável
                var d = $(this);
                c.incellClick = true;
                c.cellEditorClicked = true;	// prevent from executing the next event (click.datatable-cell-blur[DataTableId] when bubbling)
                if (!d.hasClass("ui-cell-editing")) {
                    c.showCellEditor(d)
                }
            });
        	// executa ao CLICAR em QUALQUER parte do documento, inclusive nos próprios campos 'td.ui-editable-column'! (aqui está mais um dos bugs)
            $(document).off("click.datatable-cell-blur" + this.id).on("click.datatable-cell-blur" + this.id, function(d) {
            	// Este bloco foi ajustado em relação ao código original para levar em consideração 'cellEditorClicked' (não existia) e não 'incellClick'
            	if (!c.cellEditorClicked) {
	            	if (c.currentCell && !c.contextMenuClick) {
	                    c.saveCell(c.currentCell)
	                }
                    c.incellClick = false;
            	}
                c.cellEditorClicked = false;
                c.contextMenuClick = false
            });
        }
    }
};

// Resolvido problema ao abrir menu de contexto quando a coluna é editável [ div.ui-cell-editor-output ]
// Não estava selecionando a linha clicada
// TODO: seria bom depois investigar porque este evento foi originalmente desabilitado quando se clica sobre um checkbox por exemplo [ span:not(.ui-c) ]
PrimeFaces.widget.DataTable.prototype.onRowRightClick = function(c, b, f) {
//    if ($(c.target).is("td,span:not(.ui-c)")) {
    if ($(c.target).is("td,span:not(.ui-c),div.ui-cell-editor-output")) {	// só foi acrescentado ',div.ui-cell-editor-output' ao final da linha anterior em relação ao código original
        var e = $(b),
            d = this.getRowMeta(e),
            a = e.hasClass("ui-state-highlight");
        if (f === "single" || !a) {
            this.unselectAllRows()
        }
        this.selectRow(e, true);
        this.fireRowSelectEvent(d.key, "contextMenu");
        if (this.cfg.disabledTextSelection) {
            PrimeFaces.clearSelection()
        }
    }
};

// Resolvido problema ao tentar fechar dialog com ESC quando utilizado 'Dialog Framework' (dialog com iframe) 
PrimeFaces.dialog.DialogHandler.openDialog = function(e) {
    var d = e.sourceComponentId + "_dlg";
    if (document.getElementById(d)) {
        return
    }
    var h = e.sourceComponentId.replace(/:/g, "_") + "_dlgwidget",
        f = $('<div id="' + d + '" class="ui-dialog ui-widget ui-widget-content ui-corner-all ui-shadow ui-overlay-hidden" data-pfdlgcid="' + e.pfdlgcid + '" data-widgetvar="' + h + '"></div>').append('<div class="ui-dialog-titlebar ui-widget-header ui-helper-clearfix ui-corner-top"><span class="ui-dialog-title"></span></div>');
    if (e.options.closable !== false) {
        f.children(".ui-dialog-titlebar").append('<a class="ui-dialog-titlebar-icon ui-dialog-titlebar-close ui-corner-all" href="#" role="button"><span class="ui-icon ui-icon-closethick"></span></a>')
    }
    f.append('<div class="ui-dialog-content ui-widget-content" style="height: auto;"><iframe style="border:0 none" frameborder="0"/></div>');
    f.appendTo(document.body);
    var c = f.find("iframe"),
        g = e.url.indexOf("?") === -1 ? "?" : "&",
        b = e.url + g + "pfdlgcid=" + e.pfdlgcid,
        a = e.options.contentWidth || 640;
    c.width(a);
    c.on("load", function() {
        var j = $(this),
            k = j.contents().find("title");
        if (!j.data("initialized")) {
            PrimeFaces.cw("Dialog", h, {
                id: d,
                position: "center",
                sourceComponentId: e.sourceComponentId,
                sourceWidget: e.sourceWidget,
                onHide: function() {
                    var l = this;
                    this.destroyIntervalId = setInterval(function() {
                        var m = l.content.children("iframe");
                        if (m.get(0).contentWindow.PrimeFaces.ajax.Queue.isEmpty()) {
                            clearInterval(l.destroyIntervalId);
                            m.attr("src", "about:blank");
                            l.jq.remove()
                        }
                    }, 10);
                    PF[h] = undefined
                },
                // só foi acrescentada a linha abaixo para possibilitar fechar a dialog com ESC 
                closeOnEscape: e.options.closeOnEscape,
                modal: e.options.modal,
                resizable: e.options.resizable,
                draggable: e.options.draggable,
                width: e.options.width,
                height: e.options.height
            })
        }
        if (k.length > 0) {
            PF(h).titlebar.children("span.ui-dialog-title").html(k.text())
        }
        var i = e.options.contentHeight || j.get(0).contentWindow.document.body.scrollHeight + 5;
        j.height(i);
        PF(h).show();
        c.data("initialized", true)
    }).attr("src", b)
};

(function (b) {
	b.focus = function(e, d) {
	    var c = ":not(:submit):not(:button):input:visible:enabled";
	    setTimeout(function() {
	        if (e) {
	            var f = $(b.escapeClientId(e));
	            if (f.is(c)) {
	                f.focus()
	            } else {
	                f.find(c).eq(0).focus()
	            }
	        } else {
	            if (d) {
	                $(b.escapeClientId(d)).find(c).eq(0).focus()
	            } else {
	            	// Não aplicar foco no primeiro campo com onblur que reenvia o form
	            	// Só foi acrescentado not() abaixo a partir do código original
	                $(c).not("[onblur *= 'submit()']").eq(0).focus()
	            }
	        }
	    }, 250);
	    b.customFocus = true
	};
}(PrimeFaces));