// ---------------------------------------------------------------------

function dnCreateTabViews (config) {
    if (!dnCreateTabViews.registry) dnCreateTabViews.registry = {};

    var classname = config.classname;
    var tabViews = dnGetElementsByClassName(classname);
    for (var i = 0; i < tabViews.length; i++) {
        config.tabPanelMap = {};

        var firstTab = null;
        var descendants = tabViews[i].getElementsByTagName("*");
        for (var j = 0; j < descendants.length; j++) {
            if (!descendants[j].id) continue;
            if (/^tab:/i.test(descendants[j].id)) {
                var name = /^tab:(.+)$/i.exec(descendants[j].id);
                config.tabPanelMap["tab:" + name[1]] = "panel:" + name[1];
                if (!firstTab) firstTab = descendants[j].id;
            }
        }
        if (! config.tabInitSelected) config.tabInitSelected = firstTab;

        var controller = new dnTabViewController(config);
        dnCreateTabViews.registry[classname + i] = controller;
    }
}

// ---------------------------------------------------------------------
// Tab View Controller
// ---------------------------------------------------------------------

function dnTabViewController (config) {
    // Sanity check the config object.
    if (typeof(config) === "Object") {
        console.error("You must specify a configuration object.");
        return null;
    }
    else if (typeof(config.tabPanelMap) === "Object") {
        console.error("You must set supply a tabPanelMap config option.");
        return null;
    }
    
    // Instance variables.
    this.config             = config;
    this.tabPanelMap        = config.tabPanelMap;
    this.tabSelectedClass   = config.tabSelectedClass;
    this.tabUnselectedClass = config.tabUnselectedClass;
    this.showPanelCallback  = config.showPanelCallback;
    this.hidePanelCallback  = config.hidePanelCallback;
    
    // Attach onclick event handler to the tabs.
    for (var tabId in this.tabPanelMap) {
        var panelId = this.tabPanelMap[tabId];
        
        // Check that we were given good ids.
        if (!$(tabId)) {
            console.error("Failed to find element '" + tabId + "'.");
            continue;
        }
        else if (!$(panelId)) {
            console.error("Failed to find element '" + panelId + "'.");
            continue;
        }
        
        var me = this;
        var tabEvent = config.tabEvent ? config.tabEvent : "click";
        dnAddEvent(
            $(tabId),
            tabEvent,
            function (e) { dnStopPropagation(e); me.showPanelForTab(this); }
        );
    }

    if (config.tabInitSelected && config.tabInitSelected != "none")
        this.showPanelForTab($(config.tabInitSelected));
}

// ---------------------------------------------------------------------
// dnTabViewController.showPanelForTab()

dnTabViewController.prototype.showPanelForTab = function (tab) {
    var panelId = this.tabPanelMap[tab.id];
    
    this.hideAll();
    if (this.tabSelectedClass) tab.className = this.tabSelectedClass;
    $(panelId).style.display = "block";
    if (this.showPanelCallback)
        this.showPanelCallback(tab);
    tab.dnSelectedTab = true;
}

// ---------------------------------------------------------------------
// dnTabViewController.hideAll()

dnTabViewController.prototype.hideAll = function () {
    for (var tabId in this.tabPanelMap) {
        var panelId = this.tabPanelMap[tabId];
        
        if (!$(panelId)) {
            console.error("Failed to find element '" + panelId + "'.");
            continue;
        }
        
        if (this.tabUnselectedClass)
            $(tabId).className = this.tabUnselectedClass;
        $(panelId).style.display = "none";
        if (this.hidePanelCallback)
            this.hidePanelCallback($(tabId));
        $(tabId).dnSelectedTab = false;
    }
}

// ---------------------------------------------------------------------
// dnTabViewController.positionPanelUnderTab(tab, panelId, offset)
//
// This function will position the panel under the selected tab.
//
// A different but similar function would be needed to position
// the panel to the right of a selected dojigger.

dnTabViewController.prototype.positionPanelUnderTab = function (tab, offset) {
    var panelId = this.tabPanelMap[tab.id];

    // Firefox seems to want this set before you ask for the offsets
    $(panelId).style.position = "absolute";

    // We set the menu to nowrap temporarily to get the correct width
    var originalWSSetting = $(panelId).style.whiteSpace;
    $(panelId).style.whiteSpace = "nowrap";

    // Figure out what the left offset of the menu should be
    var position = dnFindPos(tab)[0] + offset;
    var width = $(panelId).offsetWidth;
    var maxWidth = $("dnMenu").offsetWidth + offset;
    if (position + width > maxWidth)
        position = maxWidth - width;
    if (position < 0)
        position = 0;

    // Now that we have the correct width,
    // restore the original whitespace setting
    $(panelId).style.whiteSpace = originalWSSetting;

    // Set the left position of the panel
    $(panelId).style.left = position + "px";
}

// ---------------------------------------------------------------------

