var Tabs = function(){
    return {

        /**
         * The javascript library for the module using the tabs
         */
        moduleLib                       : null,
        selected                        : {tabID        : null,
                                           subtabID     : null},
        loadingMsg                      : null,
        loadingTimeout                  : 0,
        cache                           : {},

        /**
         * Initializes tabs interface
         */
        init : function(){

            $('div.tabs ul.tab').makeClickable();

            Tabs.initTabsWithOptions();
            Tabs.initSubtabs();

            /* Show tabs once page is loaded */
//            $('div.tabs').slideDown();
        },

        /**
         * Initializes tabs which have sub-options by making them clickable
         * to show/hide the sub-options interface.
         */
        initTabsWithOptions : function(){

            $('div.tabs ul.tab.has-options').click(function(){

                var tabID                   = $(this).attr('id');
                var oldTabID                = Tabs.selected.tabID;

                // Close old
                if (oldTabID != null) {
                    Tabs.closeTabOptions(oldTabID);
                }
                // Open new
                if (tabID !== oldTabID) {
                    Tabs.openTabOptions(tabID);
                }
            });
        },

        /**
         * Initializes subtabs by making them clickable
         */
        initSubtabs : function(){

            $('div.options-subtabs ul.subtab').click(function(){

               var subtabID                 = $(this).attr('id');
               Tabs.selectSubtab(subtabID);
               Tabs.load();
            });
        },

        /**
         * Opens the tab options interface (subtabs and/or options content)
         *
         * @param string tabID The id of the tab to open
         */
        openTabOptions : function(tabID){

            if (typeof Notice !== 'undefined') {
                Notice_inline.hide();
            }
            
            /* Darken all tabs */
            $('div.tabs ul.tab').removeClass('light');
            $('.tab-options').hide();

            var baseName                    = Tabs.extractBaseName(tabID);

            $('#'+baseName+'-options').show();
            $('#'+baseName+'-tab').addClass('light');
            $('#'+baseName+'-tab a.more-options').addClass('open');

            Tabs.origTabID                  = Tabs.selected.tabID;
            Tabs.selected.tabID             = tabID;
            Tabs.selectSubtab();

            if ($('#' + baseName + '-options div.options-content').html() == '') {
                Tabs.load();
            }
        },

        /**
         * Closes the tab options interface
         *
         * @param string tabID The id of the tab to close
         */
        closeTabOptions : function(tabID){

            Tabs.selected.tabID             = Tabs.origTabID;
            Tabs.selected.subtabID          = null;
            
            var baseName                    = Tabs.extractBaseName(tabID);
            $('#' + baseName + '-options div.options-content').html('');

            $('#'+baseName+'-options').hide();
            $('#'+baseName+'-tab').removeClass('light');
            $('#'+baseName+'-tab a.more-options').removeClass('open');
        },

        /**
         * Selects a subtab and loads options content using module lib
         *
         * @param string subtabID The id of the selected subtab
         */
        selectSubtab : function(subtabID){

            /* If no subtabID is specified, get id of default subtab */
            if (subtabID == undefined){
                var subtabID                = Tabs.getDefaultSubtabID();
            }
            
            /* If there is still no subtabID available, then this tab doesn't have subtabs */
            if (subtabID == undefined){
                return false;
            }

            var tabBaseName                 = Tabs.extractBaseName(subtabID);
            var tabOptionsContent           = $('#'+tabBaseName+'-options div.options-content');

            /* De-select all subtabs */
            $('div.options-subtabs ul.subtab').removeClass('down');

            /* Select the current subtab */
            $('#'+subtabID).addClass('down');
            Tabs.selected.subtabID          = subtabID;
        },

        /**
         * Loads tab content, either via AJAX or from the DOM
         */
        load : function(){

            var metadata                    = Tabs.getTabMetadata();

            if (metadata == false){
                return false;
            } else if (metadata.loadBy.toLowerCase() == 'ajax'){
                Tabs.loadByAJAX(metadata);
            } else {
                Tabs.loadByDOM(metadata);
            }
        },

        /**
         * Fetches tab content from server via AJAX, then caches results in local js cache.
         * Subsequent requests pull content from cache.
         *
         * @param object metadata Metadata for the selected tab/subtab
         */
        loadByAJAX : function(metadata){

            /* If content has already been request once, fetch it from local js cache */
            if (Tabs.isCached()) {

                var content = Tabs.getFromCache();
                metadata.callback(content);

            }
            /* Otherwise, fetch content from server via AJAX */
            else {

                /* Show loading message */
                Tabs.displayContent(Tabs.loadingMsg);

                $.ajax({
                    type: 'GET',
                    url: metadata.requestURL,
                    data: metadata.requestParams,
                    success: function(result){
                        var content             = response.process(result);
                        Tabs.addToCache(content);
                        metadata.callback(content);
                    }
                });
            }
        },

        loadByDOM : function(metadata){

            if (Tabs.selected.subtabID == null){
                var tabBaseName                = Tabs.extractBaseName(Tabs.selected.tabID);
                var content                    = $('#'+tabBaseName+'-content').html();
            } else {
                var subtabBaseName             = Tabs.extractBaseName(Tabs.selected.subtabID);
                var content                    = $('#'+subtabBaseName+'-content').html();
            }
            
            Tabs.addToCache(content);
            metadata.callback(content);
        },

        /**
         * Displays content in the tab options container for the selected tab.
         * This is the default callback function if none is specified by the
         * module lib.
         *
         * @param string content The content to display
         */
        displayContent: function(content){

            if (typeof Notice !== 'undefined') {
                Notice_inline.hide();
            }

            var tabBaseName                     = Tabs.extractBaseName(Tabs.selected.tabID);
            var tabOptionsContent               = $('#'+tabBaseName+'-options div.options-content');
            tabOptionsContent.html(content);
        },

        /**
         * Adds tab content to local js cache
         *
         * @param string content The content to cache
         */
        addToCache : function(content){

            var cacheKey                        = Tabs.getCacheKey();
            Tabs.cache[cacheKey]                = content;
        },

        /**
         * Checks whether content for the selected tab is cached
         *
         * @return boolean
         */
        isCached : function(){

            var cacheKey                        = Tabs.getCacheKey();
            return (Tabs.cache[cacheKey] !== undefined);
        },

        /**
         * Gets current tab content from cache
         *
         * @return boolean
         */
        getFromCache : function(){

            var cacheKey                        = Tabs.getCacheKey();
            return Tabs.cache[cacheKey];
        },

        /**
         * Creates string to use as key for caching current tab/subtab content
         */
        getCacheKey : function(){
            return Tabs.selected.tabID+'|'+Tabs.selected.subtabID;
        },

        /**
         * Gets the metadata for the tab from the moduleLib, setting defaults
         * for any properties not explicitly specified
         *
         * @param string subtabID The id of the selected subtab
         */
        getTabMetadata : function(){

            /* Try to get metadata for selected subtab */
            var subtabID                        = Tabs.selected.subtabID;

            if (Tabs.moduleLib.tabsMetadata != undefined) {
                var metadata                    = Tabs.moduleLib.tabsMetadata[subtabID];
            }

            /* If there's no metadata for the subtab, try getting it for the selected tab */
            if (metadata == undefined){
                var tabID                       = Tabs.selected.tabID;
                var metadata                    = Tabs.moduleLib.tabsMetadata[tabID];
            }

            /* If there's still no metadata, then we can't continue */
            if (metadata == undefined){
                return false;
            }

            /* Default to ajax request to moduleLib's ajaxURL, if nothing else is
             * specified */
            if (metadata.loadBy == undefined){
                metadata.loadBy                 = 'ajax';
            }
            if (metadata.requestURL == undefined && Tabs.moduleLib.ajaxURL !== undefined){
                metadata.requestURL             = Tabs.moduleLib.ajaxURL;
            } else if (metadata.loadBy == 'ajax' && metadata.requestURL == undefined){
                alert('Error loading tab options. Missing AJAX url.');
            }
            /* If no callback function is specified, default is to display tab content */
            if (metadata.callback == undefined || (typeof(metadata.callback) !== 'function')){
                metadata.callback               = Tabs.displayContent;
            }
            return metadata;
        },

        /**
         * Gets the default subtab id, if none is specified
         */
        getDefaultSubtabID : function(){
            var tabBaseName                     = Tabs.extractBaseName(Tabs.selected.tabID);
            return $('#'+tabBaseName+'-options div.options-subtabs ul.subtab:first').attr('id');
        },

        /**
         * Extracts the base name of the subtab or tab by stripping the suffix
         * from the id
         *
         * @param string id The id of the subtab or tab
         */
        extractBaseName : function(id){

            var subtabIndex                     = id.indexOf('-subtab');
            var tabIndex                        = id.indexOf('-tab');
            return (subtabIndex !== -1) ? id.substring(0,subtabIndex) : id.substring(0,tabIndex);
        },

        /**
         * Sets the module lib that will be used to get the tab options content
         *
         * @param object moduleLib The module's javascript library
         */
        setModuleLib : function (moduleLib){
            Tabs.moduleLib                      = moduleLib;
        }
    }
}();
$(document).ready(Tabs.init);