jQuery.fn.showModal = function(options, on_close)
{
    var layerID = "overlay_123456789";
    $("body").append("<div id='" + layerID + "' style='position:absolute; z-index:99997'></div>");

    var modalLayer = $("#" + options.modal_window.id);
    var modalCloseButtonLayer = $("#" + options.modal_window.close_button.id);

    var overlayX = 0;
    var overlayY = 0;
    var overlayWidth = Math.round($(window).width());
    var overlayHeight = Math.round($(window).height());

    var modalWidth = Math.round(modalLayer.outerWidth());
    var modalHeight = Math.round(modalLayer.outerHeight());
    var modalX = Math.round(($(window).width() / 2) - (modalWidth / 2) + $(window).scrollLeft());
    var modalY = Math.round(($(window).height() / 2) - (modalHeight / 2) + $(window).scrollTop());

    var hostLayer = this;
    var overLayer = $("#" + layerID);

    if (typeof (hostLayer) != "undefined" && typeof (overLayer) != "undefined")
    {
        overlayX = hostLayer.position().left;
        overlayY = hostLayer.position().top;
        overlayWidth = hostLayer.outerWidth();
        overlayHeight = getOuterlayHeight(options, hostLayer.outerHeight());
    }

    // handle overlay
    overLayer.css({ "background": options.overlay.background, "left": overlayX + "px", "top": overlayY + "px", "width": overlayWidth + "px", "height": overlayHeight + "px" }).bind("click", function(event)
    {
        event.preventDefault();
    }).fadeTo(0, options.overlay.opacity, function()
    {
        // handle modal window
        modalLayer.css({ "position": "absolute", "z-index": 99998, "left": modalX + "px", "top": modalY + "px", "width": modalWidth + "px", "height": modalHeight + "px", "display": "block" });
        // handle close button 
        modalCloseButtonLayer.css({ "position": "absolute", "z-index": 99999, "left": modalWidth + options.modal_window.close_button.offsetX + "px", "top": options.modal_window.close_button.offsetY + "px" }).bind("click", function()
        {
            overLayer.fadeTo(0, "1", function()
            {
                overLayer.hide();
                modalLayer.hide();
                if (on_close) on_close();
            });
        });
    });

    // handle window resize and scroll
    $(window).bind("resize scroll", function()
    {
        overLayer.css({ "width": hostLayer.outerWidth() + "px", "height": getOuterlayHeight(options, hostLayer.outerHeight()) + "px" });
        modalLayer.css({ "left": (($(window).width() / 2) - (modalWidth / 2) + $(window).scrollLeft()) + "px", "top": (($(window).height() / 2) - (modalHeight / 2) + $(window).scrollTop()) + "px" });
    });
};

jQuery.fn.hideModal = function()
{
    var modalLayer = this;
    var overLayer = $("#overlay_123456789");
    if (overLayer)
    {
        overLayer.fadeTo(0, "1", function()
        {
            overLayer.hide();
            modalLayer.hide();
        });
    }
};

jQuery.fn.disableLayer = function()
{
    var layerID = "disable_overlay_" + this.attr("id");

    if ($("#" + layerID).attr("id")) // overlay layer existing so do nothing
        return;

    // create layer
    $("body").append("<div id='" + layerID + "' style='position:absolute; z-index:99997'></div>");

    var overlayX = 0;
    var overlayY = 0;
    var overlayWidth = $(window).width();
    var overlayHeight = $(window).height();

    var hostLayer = this;
    var overLayer = $("#" + layerID);

    if (typeof (hostLayer) != "undefined" && typeof (overLayer) != "undefined")
    {
        overlayX = hostLayer.position().left;
        overlayY = hostLayer.position().top;
        overlayWidth = hostLayer.outerWidth();
        overlayHeight = hostLayer.outerHeight();
    }
    // handle overlay
    overLayer.css({ "left": overlayX + "px", "top": overlayY + "px", "width": overlayWidth + "px", "height": overlayHeight + "px" }).bind("click", function(event)
    {
        event.preventDefault();
    });
    // handle window resize and scroll
    $(window).bind("resize", function()
    {
        overLayer.css({ "width": hostLayer.outerWidth() + "px", "height": hostLayer.outerHeight() + "px" });
    });
}

jQuery.fn.enableLayer = function()
{
    var layerID = "disable_overlay_" + this.attr("id");
    $("#" + layerID).remove();
}

function getOuterlayHeight(options, currentHeight)
{
    var h = currentHeight;
    var exclude_layers_ids = options.exclude_bottom_layer_ids;
    if (exclude_layers_ids.length) // exclude these layers if specified
    {
        var x = 0;
        for (x = 0; x < exclude_layers_ids.length; x++)
        {
            var thisID = $("#" + exclude_layers_ids[x]);
            if (thisID) h -= thisID.outerHeight(); // subtract height of each layer from overlay
        }
    }
    return h;
}
