/**
 * Objet global définissant l'espace de nom Overlay
 * 
 * v 0.4.2
 * 
 * @namespace Overlay
 */
var Overlay = {};

Overlay.idNumber = 1;
Overlay.overlayInfoStack = new Array();
Overlay.closeTooltip = "Close";
Overlay.classPrefix = "overlay";

Overlay.Info = function (overlayId, escapeClose, otherCloseKey) {
    this.overlayId = overlayId;
    this.escapeClose = escapeClose;
    this.otherCloseKey = otherCloseKey;
    this.afterEnd = null;
    this.beforeEnd = null;
};

Overlay.addEscapeKeyHandler = function (target) {
    $(target).on('keydown.overlay', function (event) {
        var lastOverlayInfo = Overlay.getLastOverlayInfo();
        if (lastOverlayInfo) {
            let closeEvent = false;
            if (lastOverlayInfo.escapeClose) {
                if (event.key === "Escape") {
                    closeEvent = true;
                }
            }
            if ((!closeEvent) && (lastOverlayInfo.otherCloseKey)) {
                if (event.key === lastOverlayInfo.otherCloseKey) {
                    closeEvent = true;
                }
            }
            if (closeEvent) {
                event.preventDefault();
                event.stopPropagation();
                Overlay.end(lastOverlayInfo.overlayId);
            }
        }
        
    });
};

Overlay.removeEscapeKeyHandler = function (target) {
    $(target).off('keydown.overlay');
};

Overlay.getLastOverlayInfo = function () {
    var length = Overlay.overlayInfoStack.length;
    if (length > 0) {
        return Overlay.overlayInfoStack[length - 1];
    } else {
        return null;
    }
};

Overlay.getOverlayInfo = function (overlayId) {
    for(let overlayInfo of Overlay.overlayInfoStack) {
        if (overlayInfo.overlayId === overlayId) {
            return overlayInfo;
        }
    }
    return null;
};

Overlay.removeOverlayInfo = function (overlayId) {
    for(let i = 0, len = Overlay.overlayInfoStack.length; i < len; i++) {
        let overlayInfo = Overlay.overlayInfoStack[i];
        if (overlayInfo.overlayId === overlayId) {
            Overlay.overlayInfoStack.splice(i, 1);
            break;
        }
    }
    if (Overlay.overlayInfoStack.length === 0) {
        Overlay.removeEscapeKeyHandler(document);
    }
};

Overlay.addOverlayInfo = function (overlayInfo) {
    if (Overlay.overlayInfoStack.length === 0) {
        Overlay.addEscapeKeyHandler(document);
    }
    Overlay.overlayInfoStack.push(overlayInfo);
};

Overlay.start = function (settings) {
    var closeTooltip = Overlay.closeTooltip;
    if (settings.closeTooltip) {
        closeTooltip = settings.closeTooltip;
    }
    var overlayIdNumber = Overlay.idNumber;
    Overlay.idNumber++;
    var overlayId = "overlay_" + overlayIdNumber;
    var overlayInfo = new Overlay.Info(overlayId, _checkSetting("escapeClose", true));
    Overlay.addOverlayInfo(overlayInfo);
    var $overlayBlocker = $(_getDiv("blocker")).attr("data-overlay-role", "blocker").attr("tabindex", "-1");
    var $overlayDialog = $(_getDiv("dialog")).appendTo($overlayBlocker);
    $("body")
        .append($overlayBlocker)
        .css('overflow','hidden');
    var overlayBody = _getDiv("header") +  _getDiv("content") + _getDiv("footer");
    var includeForm = false;
    if (settings.formAttrs || settings.ajaxForm || settings.formSubmit) {
        includeForm = true;
        var $form = $("<form/>");
        if (settings.formAttrs) {
            for(var prop in settings.formAttrs) {
                $form.attr(prop, settings.formAttrs[prop]);
            }
        }
        if (settings.ajaxForm) {
            var initialBeforeSubmit = settings.ajaxForm.beforeSubmit;
            settings.ajaxForm.beforeSubmit = function (arr, $form, options) {
                if ((initialBeforeSubmit) && (initialBeforeSubmit(arr, $form, options) === false)) {
                    return false;
                }
                _startWaiting();
            };
            var initialSuccess = settings.ajaxForm.success;
            settings.ajaxForm.success = function (data, textStatus, jqXHR, $form) {
                _endWaiting();
                initialSuccess(data, textStatus, jqXHR, $form);
            };
            $form.ajaxForm(settings.ajaxForm);
        } else if (settings.formSubmit) {
            $form.submit(function () {
                return settings.formSubmit($(this));
            });
        }
        $overlayDialog.append($form.html(overlayBody));
        $form.data("overlayId", overlayId);
    } else {
        $overlayDialog.html(overlayBody);
    }
    _setContent("header", settings.header);
    _setContent("content", settings.content);
    _setContent("footer", settings.footer);
    var clickClose = _checkSetting("clickClose", true);
    var showClose = _checkSetting("showClose", true);
    $overlayBlocker
        .click(function() {
            if (clickClose) {
                Overlay.end(overlayId);
            }
        })
        .css("z-index", 10000 + overlayIdNumber);
    overlayInfo.beforeEnd = settings.beforeEnd;
    overlayInfo.afterEnd = settings.afterEnd;
    if (showClose) {
        $overlayDialog
            .append("<button data-overlay-role='close' class='" + Overlay.classPrefix + "-button-Close' title='" +  closeTooltip + " (Esc)'>&times</button>")
            .on("click.overlay", "[data-overlay-role='close']", function () {
                Overlay.end(overlayId);
            });
    }
    $overlayDialog
        .click(function (event) {
            event.stopPropagation();
        });
    if (settings.isWaiting) {
        _startWaiting();
    }
    $overlayBlocker.fadeIn(function () {
        $overlayDialog.show();
        if (settings.afterStart) {
            settings.afterStart(overlayId, _endWaiting);
        } else if (includeForm) {
            $overlayDialog.find(":input").filter("[type!='hidden']").first().trigger("focus");
        }
        setTimeout(function () {
            overlayInfo.otherCloseKey =  _checkSetting("closeKey", null);
        }, 300);
    });
    
    return overlayId;
    
    function _checkSetting(propName, defaultValue) {
        if (settings.hasOwnProperty(propName)) {
            return settings[propName];
        }
        return defaultValue;
    }
    
    function _setContent (name, content) {
        let $element = $("#" + _getId(name));
        if (!content) {
            $element.remove();
        } else if (content.jquery) {
            $element.empty().append(content);
        } else {
            $element.empty().html(content);
        }
    }
    
    function _startWaiting() {
        $overlayBlocker.find("[type='submit']").prop("disabled", true);
        $overlayBlocker.addClass(Overlay.classPrefix + "-Waiting");
    }
    
    function _endWaiting() {
        $overlayBlocker.find("[type='submit']").prop("disabled", false);
        $overlayBlocker.removeClass(Overlay.classPrefix + "-Waiting");
    }
    
    function _getDiv(name) {
        return "<div id='" + _getId(name) + "' class='" + _getClass(name) + "'></div>";
    }
    
    function _getId(name) {
        return overlayId + "_" + name;
    }
    
    function _getClass(suffix) {
        if ((settings.classes) && (settings.classes.hasOwnProperty(suffix))) {
            return settings.classes[suffix];
        }
        let prefix = Overlay.classPrefix + "-Component_";
        if (settings.classPrefix) {
            prefix = settings.classPrefix;
        }
        if ((settings.supplementaryClasses) && (settings.supplementaryClasses.hasOwnProperty(suffix))) {
            return prefix + suffix + " " + settings.supplementaryClasses[suffix];
        } else {
            return prefix + suffix;
        }
    }
};

Overlay.end = function (overlayId, callback) {
    if ((overlayId) && (overlayId.jquery)) {
        overlayId = overlayId.data("overlayId");
    }
    if (!overlayId) {
        return;
    }
    var overlayInfo = Overlay.getOverlayInfo(overlayId);
    if (!overlayInfo) {
        return;
    }
    if (overlayInfo.beforeEnd) {
        var result = overlayInfo.beforeEnd(overlayId);
        if (result === false) {
            return;
        }
    }
    var afterEnd = overlayInfo.afterEnd;
    Overlay.removeOverlayInfo(overlayId);
    $("#" + overlayId + "_blocker").empty().fadeOut(function() {
        $("#" + overlayId + "_blocker").remove();
        if ($("body").children("[data-overlay-role='blocker']").length === 0) {
            $("body").css('overflow','');
          }
        if (afterEnd) {
            afterEnd();
        }
        if (callback) {
            callback();
        }
    });
};