/**
 * Original version by Andrew Tetlaw, available at
 * http://tetlaw.id.au/view/blog/fabtabulous-simple-tabs-using-prototype/
 *
 * @author Andrew Tetlaw
 * @author icoloma 
 */
loom.ui.Tabs = Class.create({

  initialize : function(element, options) {
    this.options = Object.extend({
      selectedClass: 'selected', // css class name to apply to the selected li item
      removeUnathorizedTabs: true, // remove ajax tabs if the user does not have enough permissions to invoke them
      ajaxOptions: {}, // options to be passed to the Ajax request for asynchronous tabs, if any
      hintErrors: true // if true, tabs that contain errors will add css class "error" to the header
    }, options || {});
    this.container = $(element);
    this.options.removeUnathorizedTabs && this.container.select('a.unauthorized').each(function(e) { e.up('li').remove(); }); 
    this.links = this.container.select('a');
    this.options.hintErrors && this.links.each(this.hintTabErrors.bind(this));
    this.selectTab.bind(this).defer(this.getInitialTab()); // wait until all listeners have been registered
    this.container.observe('click', this.onClick.bind(this));
  },

  /**
   * Invoked when a tab gets clicked
   * @param link the link that has been selected by the user
   */
  selectTab: function(link) {
    this.show(link);
    this.links.without(link).each(this.hide.bind(this));
  },
  
  /**
   * If the provided tab contains components with user input errors, mark the tab header with css class="error"
   * @param link the link of the tab to test
   */
   hintTabErrors: function(link) {
	  var tab = this.getTabForLink(link.getAttribute('href'));
  	  var error = tab.down('input.error, select.error, textarea.error');
  	  link[error? 'addClassName' : 'removeClassName']('error');
  },
   
  onClick: function(e) {
    var a = e.findElement('a');
    if (a && this.links.indexOf(a) != -1) {
      e.stop();
      this.selectTab(a);
    }
  },  
  
  hide : function(a) {
    var tab = this.getTabForLink(a.href);
    if (tab.visible) { 
	    this.container.fire('tabs:deactivate', { tab: tab.id });
	  this.hintTabErrors(a, tab);
      tab.hide().removeClassName(this.options.selectedClass);
      a.up('li').removeClassName(this.options.selectedClass);
    }
  },
  
  show : function(a) {
    var href = a.getAttribute('href');
    var tab = this.getTabForLink(href);
    if (tab.innerHTML.blank()) {
	    this.container.fire('tabs:load', { tab: tab.id });
	    if (!href.startsWith('#')) {
	    	// retrieve ajax tab contents. If the response include a tag with 
	    	// the same tab id, use that; else, update the tab with the entire response contents 
	    	tab.addClassName('loading');
	    	new Ajax.Request(href.gsub(/#.*/, ''), // remove the hash before requesting
	    		Object.extend({
	    			method: 'get', // tabs by default are idempotent
		    		onSuccess: function(transport) { 
		    			tab.removeClassName('loading').update();
		    			var div = transport.responseText.toDOM();
		    			tab.innerHTML = (div.down('#' + tab.id) || div).innerHTML;
					    this.container.fire('tabs:load', { tab: tab });
		    		}.bind(this)
		    	}, this.options.ajaxOptions)
	    	);
	    }
    }
    a.up('li').addClassName(this.options.selectedClass);
    tab.show().addClassName(this.options.selectedClass);
    this.container.fire('tabs:activate', { tab: tab.id });
  },
  
  /**
   * Return the tab corresponding to a link, null if there is no hash in the link
   */
  getTabForLink: function(href) {
	var hash = href.match(/#(\w.+)/);
	return hash && $(hash[1]);
  },

  
  getInitialTab : function() {
    var tab = this.getTabForLink(document.location.href);
    var result = tab && this.links.find(function(e) { 
	      return this.getTabForLink(e.href) == tab; 
	    }.bind(this));
    return result || 
    	this.options.hintErrors && this.links.find(function(e) { return e.match('.error') }) || 
    	this.links.first();
  },
  
  observe: function(event, listener) {
  	this.container.observe(event, listener);
  }
  
});

