(function($) {

    $.lxMarathon = function(options) {
            var ctrlTabs = null;
            var aryPrevDims = null;
            var oPageTracker = null;

            var defaults = {
                selTabs: "#tabs",
                selDialog: "#dialog",
                selDialogLinks: "#footer a",
                fmtTitle: "Ulmer Laufnacht - %s",
                tabs: [
                    {title: "Starter", selPanel: "#home",     content: ["/m.einstein-marathon.de/public/registration/total"]},
                    {title: "Termine", selPanel: "#schedule", content: ["/m.einstein-marathon.de/public/schedule"]},
                    {title: "News",    selPanel: "#news",     content: ["/m.einstein-marathon.de/public/news"]},
                    {title: "Strecke", selPanel: "#track",    content: ["/m.einstein-marathon.de/public/track"]},
                ]
            };
            var o = $.extend(defaults, options)

            init();

            function init() {
                ctrlTabs = initTabs();
                intialSelectTab(ctrlTabs);
                initDialogLinks();
                initOrientationEventHandler();
            }

            function initTabs() {
                $(o.selTabs).show();
                
                var ctrlTabs = $(o.selTabs).tabs();
                bindTabSelectHandler();

                return ctrlTabs;
            }

            function bindTabSelectHandler() {
                $(o.selTabs).bind("tabsselect", onTabSelect);
            }

            function unbindTabSelectHandler() {
                $(o.selTabs).unbind("tabsselect", onTabSelect);
            }

            function initDialogLinks() {
                $(o.selDialogLinks).each(function() {
                    if ($(this).isExternalLink() == false) 
                        $(this).click(onInternalLinkClick);
                });
            }

            function intialSelectTab(ctrlTabs) {
                var idx = getCurrentTabIndex();

                var oTabDescriptor = o.tabs[idx];
                if (oTabDescriptor == null)
                    return;

                var ui = {
                    index: idx,
                    panel: $(oTabDescriptor.selPanel)
                };

                onTabSelect({}, ui);
            }

            function onTabSelect(event, ui) {
                var oTabDescriptor = o.tabs[ui.index];
                if (oTabDescriptor == null) 
                    return false;

                unbindTabSelectHandler();
                unbindOrientationChangeListeners();

                updatePageTitleByTabTile(oTabDescriptor);
                loadContentToTabPanel(ui.panel, oTabDescriptor);
                showLoadIndicatorOnOtherPanels(ui.panel);

                bindTabSelectHandler();
                return true;
            }

            function updatePageTitleByTabTile(oTabDescriptor) {
                if (oTabDescriptor == null || oTabDescriptor.title == null)
                    return;

                var strTitle = o.fmtTitle.replace("%s", oTabDescriptor.title);
                document.title = strTitle;
            }

            function loadContentToTabPanel(elPanel, oTabDescriptor) {
                if (oTabDescriptor == null || oTabDescriptor.content == null)
                    return;
              
                var loadQueue = [];
                if (typeof oTabDescriptor.content === "string") {
                    loadQueue.push(oTabDescriptor.content)
                } else if ($.isArray(oTabDescriptor.content)) {
                    loadQueue = oTabDescriptor.content.copy();
                } else {
                    return;
                }

                $(elPanel).find(".content").loadDataAndAppend(loadQueue);
            }

            function showLoadIndicatorOnOtherPanels(elPanel) {
                var elParent = $(elPanel).parent();
                var elPanelsExceptCurrent = elParent.children("div").not(elPanel);

                elPanelsExceptCurrent.each(function() {
                    $(this).find(".content").clearContentsAndShowLoadIndicator();
                });
            }

            function onInternalLinkClick(event) {
                var url = $(this).attr("href");
                var title = $(this).attr("title");

                loadContentToDialog(url);
                showDialog(title);

                return false;
            }

            function loadContentToDialog(url) {
                var elDialog = $(o.selDialog);
                elDialog.find(".content").loadDataAndAppend(url);
            }

            function closeDialog(event) {
                var elDialog = $(o.selDialog);
                elDialog.hide();

                elDialog.find(".content").clearContentsAndShowLoadIndicator();
            }

            function showDialog(title) {
                var elDialog = $(o.selDialog);

                elDialog.show();
                elDialog.find(".ui-dialog-titlebar-close").click(closeDialog);
            }

            function initOrientationEventHandler() {
                $(window).resize(onWindowResize);
                onWindowResize({});
            }

            function onWindowResize(event) {
                var aryCurrDims = [$(window).width(), $(window).height()];

                if (aryPrevDims != null) {
                    var prevOrientation = getOrientatinonFromDims(aryPrevDims);
                    var currOrientation = getOrientatinonFromDims(aryCurrDims);

                    if (prevOrientation != currOrientation) {
                        fireOrientationChangeEvent(currOrientation);
                    }
                }

                aryPrevDims = aryCurrDims.copy();
                return true;
            }

            function getOrientatinonFromDims(aryDims) {
                return aryDims[0] / aryDims[1] < 1.0 ? "portrait" : "landscape";
            }

            function fireOrientationChangeEvent(currOrientation) {
                $(window).trigger("orientationchange", currOrientation);
            }

            function unbindOrientationChangeListeners() {
                $(window).unbind("orientationchange");
            }

            function getCurrentTabIndex() {
                var idx = ctrlTabs.tabs("option", "selected");
                return idx;
            }

            function getCurrentTab()  {
                var idx = getCurrentTabIndex();

                var oTabDescriptor = o.tabs[idx];
                if (oTabDescriptor == null)
                    return false;

                var elPanel = $(oTabDescriptor.selPanel);
                return elPanel;
            }

            function isMobileWebkit() {
                var uagent = navigator.userAgent.toLowerCase();
                if (uagent.search("iphone") > -1)
                    return true;
                else if (uagent.search("ipod") > -1)
                    return true;
                else if (uagent.search("ipad") > -1)
                    return true;

                return false;
            }

            var publicInterface = {
                getCurrentTab: getCurrentTab,
                isMobileWebkit: isMobileWebkit
            };

            return publicInterface;
    }

    $.fn.extend({
        isExternalLink: function() {
            var elLink = $(this);
            return (elLink.attr('target') == '_blank' ||
                    elLink.attr('rel') == 'external' ||
                    elLink.is('input[type="checkbox"], input[type="radio"], a[href^="http://maps.google.com"], a[href^="mailto:"], a[href^="tel:"], a[href^="javascript:"], a[href*="youtube.com/v"], a[href*="youtube.com/watch"]')
            );
        },

        loadDataAndAppend: function(loadQueue, fn, idx) {
            var elContent = $(this);
            if (elContent.hasClass("content") == false)
                return;

            // Wrap single URL in array that recursion works
            if (typeof loadQueue === "string")
                loadQueue = [ loadQueue ];

            // return if queue empty
            if ($.isArray(loadQueue) && loadQueue.length == 0)
                return;

            if (idx == undefined) {
                idx = 0;
                
                // define function to hide data and fade out
                if (fn == undefined) {
                    fn = function(data) {
                        elContent.children(".load-indicator").fadeOut("fast", function() {
                            elContent.append(data);
                            elContent.loadDataAndAppend(loadQueue, undefined, (idx + 1));
                        });
                    }
                }
            }

            if (fn == undefined) {
                fn = function(data) {
                    elContent.append(data);
                    elContent.loadDataAndAppend(loadQueue, undefined, (idx + 1));
                }
            }

            var url = loadQueue;
            if ($.isArray(loadQueue))
                url = loadQueue.shift();

            
            // Track event to GA
            if(pageTracker) {
                pageTracker._trackPageview(url);
            }

            $.get(url, fn);
        },

        clearContentsAndShowLoadIndicator: function() {
            var elContent = $(this);
            if (elContent.hasClass("content") == false)
                return;

            elContent.children().not(".load-indicator").remove();
            elContent.children(".load-indicator").show();
        },

        placeholder: function() {
            // Quit if there’s support for HTML5 placeholder
            if (this[0] && 'placeholder' in document.createElement('input')) {
                // Allow chaining
                return this;
            };
            // Made this a function, because we actually need it on two different occasions:
            // 1) Once when the DOM is loaded;
            // 2) Once every time the focusout() is triggered.
            function setPlaceholder($elem) {
                if ($elem.val() === '' || $elem.val() === $elem.attr('placeholder')) {
                    $elem.addClass('placeholder').val($elem.attr('placeholder'));
                } else {
                    $elem.removeClass('placeholder');
                };
            };
            // Submit handler on all forms containing input[placeholder]
            // Needs to be via .click()
            $('form:has([placeholder]) :submit').click(function() {
                // if ($(this).has('.placeholder') never returns false here — WTF?
                if ($(this.form).find('.placeholder').length) {
                    $(this.form).find('.placeholder:first').val('').focus().removeClass('placeholder');
                    return false;
                };
            });
            return $(this).each(function() {
                var $input = $(this);
                // Quit if the current element is a password input, or not an input at all
                if ($input.is(':password') || !$input.is(':input')) {
                    return;
                };
                setPlaceholder($input);
                $input.focusin(function() {
                    if ($input.val() === $input.attr('placeholder')) {
                        $input.val('').removeClass('placeholder');
                    };
                }).focusout(function() {
                    setPlaceholder($input);
                });
            });
        }
    });

    Array.prototype.copy = function() {
        return this.slice(0, this.length);
    }


})(jQuery);
