/*************************************************************
Widget: rock.tabview
Depend: jmaki.js, rock-util.js, prototype.js, scriptaculous/Builder.js
Author: Joe Hu, joehu@unimerse.com
Verseion: 1.0.0
	
Widget attributes:
  value: JSON representing menus
  service: url to retrieve JSON string JSON representing menus
  args:
    selectedIndex - default selected tab index, 0-based. Default: 0.
    contentId - ID of the content DIV, into which content will be injected. 
    			Default: content.
    
A tab must have a url, which points to a content pag. When a tab is selected, 
the content represented by the url is retrieved and injected into the content DIV. 

When a tab is clicked, it publishes event /rock/tabview/tabClicked.
    
The tabview renders definition of menus in tab view. Example of 
menus JSON:
{menus: [
  {label: 'Home',
   url: 'home/',
   toolbarUrl: 'home/toolbar.jsp'
   },
  {label: 'Electronics',
   url: 'store/electronics/',
   toolbarUrl: 'store/electronics/toolbar.jsp'
   },  
  {label: 'Computers',
   url: 'store/computers/',
   toolbarUrl: 'store/computers/toolbar.jsp'
   },     
  {label: 'About',
    url: 'about/unimerse/',
    menuItems: [
      {label:'Unimerse', url: 'about/unimerse/'},
      {label:'Services', url: 'about/services/'}
    ]}                
]}    
***************************************************************/
 
// define the namespaces
jmaki.namespace("jmaki.widgets.rock.tabview");

jmaki.widgets.rock.tabview.Widget = function(wargs) {
	
    var uuid = wargs.uuid;
    var container = $(uuid);
    var menus = []; // array of menu definitions
    var tabListId = "tabList"; // DOM element ID for tab list
    var name = "rock.tabview";

    // args
    var contentDivId = "content";  
    var selectedIndex = 0;      

    // published events
    var topicOnTabClicked = "/rock/tabview/tabClicked";
        	
    // check arg contentId
    if (wargs.args && wargs.args.contentId) {
        contentDivId = wargs.args.contentId;
    }

    // check arg selectedIndex
    if (wargs.args && wargs.args.selectedIndex) {
        selectedIndex = Number(wargs.args.selectedIndex);
    }    
                	
    // retrieve navigation menu definitions
    if (wargs.value) {
        menus = wargs.value.menus;      
        init();
    } else if (wargs.service) {
    	// call service
	jmaki.log(name + ": making an ajax call to " + wargs.service);
	new Ajax.Request( 
	    wargs.service, // url
	    { method: 'get', 
	      onSuccess: onTabDefsRetrieved,
	      onFailure: function(req) {
		    rock.showErrorMsg("Http error: Status " + req.status + " " + 
				      req.statusText + " - " + req.responseText,
				      $(contentDivId)); 
	      },	
	      onException: function(req, exception) {
		    rock.showErrorMsg("Application exception: " + exception, 
				      $(contentDivId)); 
	      }			     
	   });
    }
    
    function onTabDefsRetrieved(req) {
	jmaki.log(name + "/onTabDefsRetrieved: responsetext= " + req.responseText);
	// turn txt into object literal
        var response = eval('(' + req.responseText + ')');  
        menus = response.menus;                      	
        init();  
    }

   function init() {               
        // create tab container div
        var tabContainer = document.createElement("div");
        Element.addClassName(tabContainer, "tabContainer");
        container.appendChild(tabContainer);
                                		
	// create tab list                               
	var tabList = createTabListDom(menus);
	//jmaki.log(name + "/init: tabList DOM = " + tabList);
	tabContainer.appendChild(tabList);
        
        // create tabToolbarContainer for each tab
        createTabToolbars(menus, container);       

        renderTabView(tabListId, selectedIndex);  
    }
    
    /*
     Given an array of menu objects, create a DOM element of unordered list 
     that is the definition of tabs.
    */
    function createTabListDom(menus){
    	var list = Builder.node('ul', {id:'tabList'});
	for (var i=0; i < menus.length; i++){	    
	    var url;
	    if(menus[i].url){
		    url = menus[i].url;
	    }
	    //jmaki.log(name + "/createTabListDom: label= " + menus[i].label + ", url= " + url);
	    var item = Builder.node('li');
	    var link;
	    if(url){
		    link = Builder.node('a', {href:'#', url:url, id:'tab_'+i}, menus[i].label);
	    }else{
		    link = Builder.node('a', {href:'#', id:'tab_'+i}, menus[i].label);
	    }
	    item.appendChild(link);
	    list.appendChild(item);

	}

	return list;
    }
    
    function createTabToolbars(menus, container){
    	var toolbarContainer, toolbar;
	for (var i=0; i < menus.length; i++){	  
	    //rock.debugAddMsg('creating tab toolbar ' + i);  	
	    toolbarContainer = Builder.node('div', 
		    {id:'tabToolbarContainer_' + i, className:'tabToolbarContainer'}, 
		    '');	  	        	
	    toolbar = Builder.node('div', 
		    {id:'tabToolbar_' + i, className:'tabToolbar'}, 
		    '');  
	    toolbarContainer.appendChild(toolbar);
	    container.appendChild(toolbarContainer); 

	    if(menus[i].toolbarUrl){
		    injectToolbar(menus[i].toolbarUrl, toolbar);
	    }

	    createTabMenu(menus[i], i, toolbarContainer);	              	
	}
    }        
    
    function createTabMenu(menu, menuIndex, toolbarContainer){
    	var menuDiv;	
    	if(menu.url){    
	        menuDiv = Builder.node('div', 
	        	{id:'tabMenu_' + menuIndex, className:'tabMenu', url:menu.url}, 
	        	'');
        }else{	
	        menuDiv = Builder.node('div', 
	        	{id:'tabMenu_' + menuIndex, className:'tabMenu'}, 
	        	'');	        		        
        }	
        toolbarContainer.appendChild(menuDiv);   

    	if(menu.menuItems){
    		createMenuItems(menu.menuItems, menuDiv);
    	}	    	

    } 
            
    function createMenuItems(menuItems, menuContainer){
    	// reverse menu items because of right float
    	menuItems.reverse();
    	
        for (var i=0; i < menuItems.length; i++){
            var menuItem = Builder.node('div',
            	{className:'tabMenuItem', url:menuItems[i].url},
            	menuItems[i].label);
            menuContainer.appendChild(menuItem);
            
            // register onclick handler
            menuItem.onclick = onMenuItemSelected;            
            
            // append spacer if not the last item
            if (i < menuItems.length - 1) {
                var spacerDiv = Builder.node('div', 
                	{className:'tabMenuItemSeparator'}, 
                	'|');
                menuContainer.appendChild(spacerDiv);
            }            
        }    
    }
    
    /*
     Initialize the tab view by processing tab list definition and
     selected tab index.
    */
    function renderTabView(tabListId, selectedIndex) {
      var tabLinks = $(tabListId).getElementsByTagName("a");

      var link, tabId, selectedUrl, tabMenuId;
      for (var i = 0; i < tabLinks.length; i++) {
	link = tabLinks[i];
	tabId = link.id;
	//jmaki.log(name + ": renderTabView: link=" + link);
	if (!tabId) alert("Expand link does not have a tabId element: " + link.innerHTML);

	if (i == selectedIndex) {
	  selectedUrl = link.getAttribute('url');
	  //jmaki.log(name + ": renderTabView: selectedUrl=" + selectedUrl);
	  link.className = "linkSelected";
	  // show tab toolbar
	  showTabToolbar(i);
	}else {
	  link.className = "linkUnselected";
	  // hide tab menu
	  hideTabToolbar(i);
	}

	// register onclick event handler
	link.onclick = onTabSelected; 
      }
	  
      
      if(selectedUrl){
        injectContent(selectedUrl);
      }	  
    }
	    
    /**
     * Event handler when a tab is clicked or programmatically selected.
     */
    function onTabSelected(){
      var tabId = this.id;	
      var tabIdx = tabId.substring(tabId.lastIndexOf("_")+1);
            
      // publish event
      jmaki.log(name + ": onTabSelected: tabId=" + tabIdx + ", tab label=" + menus[tabIdx].label);
      jmaki.publish(topicOnTabClicked, menus[tabIdx]);
            
      var tabLinks = this.parentNode.parentNode.getElementsByTagName("a");
      for (var i = 0; i < tabLinks.length; i++) {
        var link = tabLinks[i];
        var loopId = link.id;
        if (loopId == tabId) {
          link.className = "linkSelected";
	  // show tab menu
	  showTabToolbar(i);          
        }
        else {
          link.className = "linkUnselected";
	  // hide tab menu
	  hideTabToolbar(i);          
        }
      }
      
      //if (this.blur) this.blur();
	          
      // if tab url is defined, injecting the page into content area
      var url = this.getAttribute("url");     
      if(url){
	  jmaki.log(name + "/onTabSelected: tab url= " + url);
	  injectContent(url);
      }        	      
      
      return false;
    }
	     
	
    // Event handler when a menu item is clicked
    function onMenuItemSelected(){
      var url = this.getAttribute("url"); 
	              
      // publish tab url to dcontainter
      if(url){
        //jmaki.publish(topic, url);
        injectContent(url);
      }
        	      
       return false;
    }	          
    
    function showTabToolbar(tabIndex){
    	var tabToolbarContainerId = 'tabToolbarContainer_' + tabIndex;
      	rock.util.DomUtil.showElement($(tabToolbarContainerId));
    }   
	
    function hideTabToolbar(tabIndex){
      	var tabToolbarContainerId = 'tabToolbarContainer_' + tabIndex;
      	rock.util.DomUtil.hideElement($(tabToolbarContainerId));      
	}	
	
    function injectToolbar(toolbarUrl, toolbar){
	    //rock.debugAddMsg('injecting toolbar from ' + toolbarUrl + ' into ' + toolbar.id);    
	    // toolbar must be injectd synchronously
	    jmaki.injector.inject({url: toolbarUrl, injectionPoint: toolbar});       	   	    
    }
    	
    function injectContent(contentUrl){
	jmaki.log(name + '/injectContent: injecting content from ' + contentUrl);
        //jmaki.injector.inject({url: contentUrl, injectionPoint: $(contentDivId)});
        rock.injector.inject({url: contentUrl, container: $(contentDivId)});	   
    }
}
