(function($){
    var options = {
        hideBodyScrollbars : false,
        closeOnCanvasClick : true,
        closeOnEscape      : true,
        fadeInFirst        : "canvas",
        fadeOutFirst       : "dialog",
        canvasFadeInTime   : 100,
        canvasFadeOutTime  : 100,
        canvasTemplate     : '',
        canvasClass        : 'kkmodal_canvas',
        canvasColor        : 'black',
        canvasOpacity      : 0.75,
        canvasZIndex       : 200,
        loaderClass        : 'kkmodal_loader',
        loaderImage        : 'img/ajax-loader.gif',
        loaderImageClass   : 'kkmodal_loader_image',
        dialogFadeInTime   : 0,
        dialogFadeOutTime  : 0,
        dialogTemplate     : '',
        dialogClass        : 'kkmodal_dialog',
        dialogHeadlineClass: 'kkmodal_dialog_headline',
        dialogCloseClass   : 'kkmodal_dialog_close',
        dialogContentClass : 'kkmodal_dialog_content',
        dialogWidth        : 'auto',
        dialogHeight       : 'auto',
        dialogPositionX    : 'center',
        dialogPositionY    : 'center',
        dialogZIndex       : 250,
        dialogAnimateResize: true,
        dialogAnimationTime: 350,
        createDialogView   : true
    };

    $.fn.kkmodal = function(action_options, _options, postData, showCallback, hideCallback) {

        var action = "show";

        if(action_options) {
            if(typeof action_options == "string") {
                action = action_options;

                if(_options && typeof _options == "object") {
                    options = $.extend(true, options, _options);
                }
            } else if(typeof action_options == "object") {
                options = $.extend(true, options, action_options);
            }
        }

        if(action == "show") {
            if(options.fadeInFirst == "canvas") {
                showCanvas(options, true, this.eq(0), showCallback);
            } else if(options.fadeInFirst == "dialog") {
                showDialog(options, true, this.eq(0), showCallback);
            }
        } else if(action == "hide") {
            if(options.fadeOutFirst == "canvas") {
                hideCanvas(options, true, hideCallback);
            } else if(options.fadeOutFirst == "dialog") {
                hideDialog(options, true, hideCallback);
            }
        } else if(action == "setopt") {
            return this;
        } else {
            if(options.fadeInFirst == "canvas") {
                showCanvas(options, true, action, postData, showCallback);
            } else if(options.fadeInFirst == "dialog") {
                showDialog(options, true, action, postData, showCallback);
            }
        }

        return this;
    }

    function loadContent(options, url, postData) {
        var ajaxOptions = {
            url      : url,
            async    : false,
            dataType : "html",
            cache    : false,
            success  : function(html) {
                $('#' + urlToID(url)).remove();
                $(document.body).append('<div id="' + urlToID(url) + '">' + html + '</div>');
            }
        };

        ajaxOptions.type = postData ? "POST" : "GET";

        if(postData) ajaxOptions.data = postData;

        $.ajax(ajaxOptions);

        return url;
    }

    function getCanvas(options) {
        var $canvas = $('.' + options.canvasClass);

        if($canvas.length == 0) {
            if(options.canvasTemplate != '') {
                $.ajax({
                    url      : options.canvasTemplate,
                    async    : false,
                    type     : "GET",
                    dataType : "html",
                    success  : function(html) {
                        $(document.body).append(html);
                    }
                });

                $canvas = $('.' + options.canvasClass);
            }

            if($canvas.length == 0) {
                $canvas = $('<div class="' + options.canvasClass + '"></div>');
                $(document.body).append($canvas);
                $canvas.css('background-color', options.canvasColor).hide();
            }
            var $window = $(window);
            var $document = $(document);

            $canvas.css({
                opacity : 0.0,
                position: 'absolute',
                zIndex  : options.canvasZIndex,
                top     : 0,
                left    : 0
            }).hide();

            if(options.closeOnCanvasClick) {
                $canvas.click(function() {$(document).kkmodal("hide", options);});
            }

            if(typeof $.fn.bgiframe == "function") {
                $canvas.bgiframe();
            }
        }

        return $canvas;
    }

    function getDialog(options) {
        var $dialog = $('.' + options.dialogClass);

        if($dialog.length == 0) {
            if(options.dialogTemplate != '') {
                $.ajax({
                    url      : options.dialogTemplate,
                    async    : false,
                    type     : "GET",
                    dataType : "html",
                    success  : function(html) {
                        $(document.body).append(html);
                    }
                });

                $dialog = $('.' + options.dialogClass);
            }

            if($dialog.length == 0) {
                if(options.createDialogView) {
                    $dialog = $(
                        '<div class="' + options.dialogClass + '">' +
                            '<div class="' + options.dialogHeadlineClass + '" style="text-align:right">' +
                                '<a class="' + options.dialogCloseClass + '" href="javascript:;">x</a>' +
                            '</div>' +
                            '<div class="' + options.dialogContentClass + '"></div>' +
                        '</div>'
                    );
                } else {
                    $dialog = $('<div class="' + options.dialogClass + '"><div class="' + options.dialogContentClass + '"></div></div>');
                }
                $(document.body).append($dialog);

            }

            $dialog.css({
                opacity : 0.0,
                position: 'absolute',
                zIndex  : options.dialogZIndex
            }).hide();

            $('.' + options.dialogCloseClass, $dialog).click(function() {
                $(document).kkmodal("hide", options);
            });

            if(options.closeOnEscape) {
                $(window).keyup(function(event) {
                    if(event.keyCode == 27) {
                        $(document).kkmodal("hide", options);
                    }
                });
            }
        }

        return $dialog;
    }

    function getLoader(options) {
        var $loader = $('.' + options.loaderClass);

        if($loader.length == 0) {
            $loader = $(
                '<div class="' + options.loaderClass + '">' +
                    '<img class="' + options.loaderImageClass + '" src="' + options.loaderImage + '" style="position:absolute" border="0">' +
                '</div>'
            );
            $(document.body).append($loader);
            $loader.css('position', 'absolute').hide();
        }

        return $loader;
    }

    function showCanvas(options, doShowDialog, dialogSource, postData, showCallback) {
        var $canvas = getCanvas(options);

        if(!$canvas.is(':visible')) {
            $canvas.css({
                opacity : 0.0,
                top     : 0,
                left    : 0,
                width   : $(window).width(),
                height  : $(document).height()
            }).show().fadeTo(
                options.canvasFadeInTime, options.canvasOpacity, function() {
                    if(options.hideBodyScrollbars) {
                        $(document.body).css('overflow', 'hidden');
                    }

                    if(doShowDialog) {
                        showDialog(options, false, dialogSource, postData, showCallback);
                    }
                }
            );
        } else {
            if(doShowDialog) {
                showDialog(options, false, dialogSource, postData, showCallback);
            }
        }
    }

    function hideCanvas(options, doHideDialog, hideCallback) {
        var $canvas = getCanvas(options);

        $canvas.fadeTo(
            options.canvasFadeOutTime, 0.0, function() {
                if(doHideDialog) {
                    hideDialog(options, false, hideCallback);
                }

                $canvas.hide();
                $(document.body).css('overflow', 'auto');
            }
        );
    }

    function showDialog(options, doShowCanvas, source, postData, showCallback) {
        var $dialog = getDialog(options);
        var $content = $('.' + options.dialogContentClass, $dialog);

        if(!$dialog.is(':visible')) {
            $dialog.css('opacity', 0.0).show().fadeTo(
                options.dialogFadeInTime, 1.0, function() {
                    if(doShowCanvas) {
                        showCanvas(options, false, null);
                    }

                    showDialog(options, false, source, postData, showCallback);
                }
            );

            return;
        }

        if(typeof source == "string") {
            var $loader = $('.' + options.loaderClass);
            var $html = $('#' + urlToID(source));

            if($loader.length == 0) {
                $loader = getLoader(options);
                $loader.appendTo($dialog);
            }

            $loader.appendTo($content).css({
                top    : 0,
                left   : 0,
                width  : "100%",
                height : "100%"
            }).show();

            if($content.children().length == 0) {
                $content.append('<div style="width:100px;height:100px"></div>');
            }

            var $img = $loader.children('img').eq(0);

            if($content.width() < 15) {
                $content.css({
                    width : 100,
                    height: 100
                });
            }

            var loaderImageWidth     = $img.width();
            var loaderImageHeight    = $img.height();
            var currentContentWidth  = $content.width();
            var currentContentHeight = $content.height();

            $img.css({
                top  : ( $content.outerHeight() - loaderImageHeight ) / 2,
                left : ( $content.outerWidth() - loaderImageWidth ) / 2
            });

            updatePosition(options, $dialog);

            if(loadContent(options, source, postData)) {
                $html = $('#' + urlToID(source));
            } else {
                $html = $('<p style="color:red">Fehler: URL "' + source + '" konnte nicht geladen werden!</p>');
            }

            $content.children().appendTo(document.body).hide();
            $html.appendTo($content).show();
            $content.css({width : "auto", height : "auto"});

            if(options.dialogAnimateResize) {
                var targetContentWidth       = $content.width();
                var targetContentHeight      = $content.height();
                var targetContentOuterWidth  = $content.outerWidth();
                var targetContentOuterHeight = $content.outerHeight();
                var dialogTargetWidth        = $dialog.width();
                var dialogTargetHeight       = $dialog.height();

                if(targetContentWidth != currentContentWidth || targetContentHeight != currentContentHeight) {
                    $loader.appendTo($content).show();
                    $content.css({width : currentContentWidth, height : currentContentHeight});

                    $content.animate({
                        width  : targetContentWidth,
                        height : targetContentHeight
                    }, options.dialogAnimationTime, null, function() {
                        $loader.hide().appendTo($dialog);
                    });

                    $img.animate({
                        top  : ( targetContentOuterHeight - loaderImageHeight ) / 2,
                        left : ( targetContentOuterWidth - loaderImageWidth ) / 2
                    }, options.dialogAnimationTime);

                    $dialog.animate({
                        top  : (( $(window).height() - dialogTargetHeight ) / 2) + $(document).scrollTop(),
                        left : ( $(window).width() - dialogTargetWidth ) / 2
                    }, options.dialogAnimationTime);
                } else {
                    $loader.hide().appendTo($dialog);
                    updatePosition(options, $dialog);
                }
            } else {
                $loader.hide().appendTo($dialog);
                updatePosition(options, $dialog);
            }
        } else {
            $content.children().appendTo(document.body).hide();
            $(source).appendTo($content).show();
            updatePosition(options, $dialog);
        }

        if(typeof showCallback == "function") {
            showCallback.apply(null, [ $dialog ]);
        }
    }

    function hideDialog(options, doHideCanvas, hideCallback) {
        var $dialog = getDialog(options);

        $dialog.fadeTo(
            options.dialogFadeOutTime, 0.0, function() {
                if(doHideCanvas) {
                    hideCanvas(options, false);
                }

                $dialog.hide();

                if(typeof showCallback == "function") {
                    hideCallback.apply(null);
                }

                $('.' + options.dialogContentClass, $dialog).children().appendTo(document.body).hide();
            }
        );
    }

    function urlToID(string) {
        return string.replace(/[^a-z]+/gi, '-');
    }

    function updatePosition(options, $dialog) {
        if(!$dialog) $dialog = getDialot(options);

        $dialog.css({width : 'auto', height: 'auto'}).css ({
            top   : (( $(window).height() - $dialog.height() ) / 2) + $(document).scrollTop(),
            left  : ( $(window).width() - $dialog.width() ) / 2
        });
    }
})(jQuery)

