/*  Dynamic table control, version 1.0.0
 *
 *  (c) 2007 Sven Rymenants - Byteworks - www.byteworks.be
 *
/*--------------------------------------------------------------------------*/
var MenuCtrl = Class.create();

Effect.Chain = Class.create();
Object.extend(Effect.Chain.prototype, {
    initialize: function(effect, elements, options){
        this.elements = elements || [];
        this.effect = effect;
        this.options = options || {};
        this.afterFinish = this.options.afterFinish || Prototype.emptyFunction;
        this.options.afterFinish = this.nextEffect.bind(this);
        setTimeout(this.nextEffect.bind(this), 1);
    },
    nextEffect: function(){
        if(this.elements.length)
            new Effect[this.effect](this.elements.shift(), this.options);
        else
            this.afterFinish();
    }
});

function menuItem(id, pid, name)
{
  this.id = id;
  this.pid = pid;
  this.name = name;
  this._hasChildren = false;
  this._parent = null;
  this._selected = false;
};

MenuCtrl.prototype = {
  initialize: function(element)
  {
    var options = Object.extend({
      onSelect: null
    }, arguments[1] || {});

    this._options = options;

    this._name         = element;
    this._element      = document.getElementById(element);

    this._aAppearStack = [];
    this._aHideStack   = [];
    this._aItems       = [];
    this._selectedItem = null;
    this._appearFrom   = 0;
    this._itemOffset   = this._name.length + 1;
    
    this.clickMenu = this._clickMenu.bindAsEventListener(this);
    
    Event.observe(this._element, "click", this.clickMenu);
  },

 	destroy: function()
 	{
  	Event.stopObserving(this._element, "click", this.clickMenu);
	},
  
  addItem: function(id, pid, name)
  {
    this._aItems[this._aItems.length] = new menuItem(id, pid, name);
    var newItem = this._aItems[this._aItems.length-1];
    if (pid != 0)
    {
      newItem._parent = this._getElement(pid);
      newItem._parent._hasChildren = true;
    }
  },

  refresh: function()
  {
    if (this._aHideStack.length > 0)
    {
      new Effect.Chain(
         'BlindUp', // The effect name
         this._aHideStack,  // an array of elements
         { duration: 0.5,  // options for the effect itself
         afterFinish: function() { menu._handleHide(); }}
      );
      return;
    }
    
    this._render();
    
    if (this._aAppearStack.length > 0)
    {
      //for(var i=0; i<this._aAppearStack.length; ++i)
      //  this._aHideStack.push(this._aAppearStack[i]);

      new Effect.Chain(
        'BlindDown',
        this._aAppearStack,
        { duration: 0.5 }
      );
    }
  },
  
  _handleHide: function()
  {
    this._render();
    
    if (this._aAppearStack.length > 0)
    {
      //for(var i=0; i<this._aAppearStack.length; ++i)
      //  this._aHideStack.push(this._aAppearStack[i]);

      this._aAppearStack.reverse(true);
      new Effect.Chain(
        'BlindDown',
        this._aAppearStack,
        { duration: 0.5 }
      );
    }
  },
  
  _render: function()
  {
    var width = this._element.getDimensions().width;
    var aMenu = [];
    var aSelect = [];
    var finished = false;
    var displayLevel = false;
    
    var renderParent = 0;
    if (this._selectedItem)
    {
      renderParent = this._selectedItem.id;
      aSelect.push(this._name + '_item' + this._selectedItem.id);
    }

    do
    {
      var aThisMenu = [];
      for (var i=0; i<this._aItems.length; i++)
      {
        if (this._aItems[i].pid == renderParent)
          aThisMenu.push(this._aItems[i]);
      }   

      if ((aThisMenu.length == 0) && this._selectedItem)
      {
        //Selected element has no children.
        renderParent = this._selectedItem.pid;
        finished = false;
        continue;
      }

      //itemWidth = (width - (aThisMenu.length * 2)) / aThisMenu.length;
      itemWidth = parseInt(width / aThisMenu.length);

      if (renderParent == this._appearFrom)
        displayLevel = true;
      aMenu.push('<div id="' + this._name + '_level' + renderParent + '"');
      if ((renderParent != 0) && !displayLevel)
      {
        aMenu.push(' style="display:none"');
        this._aAppearStack.push(this._name + '_level' + renderParent);
      }
        
      aMenu.push('>');
      for (var i=0; i<aThisMenu.length; i++)
      {
        aMenu.push('<div id="' + this._name + '_item' + aThisMenu[i].id + '" style="width:' +  itemWidth + 'px">' + aThisMenu[i].name + '</div>');
      }
      aMenu.push('</div>');
     
      finished = (renderParent == 0);
      if (!finished)
      {
        aSelect.push(this._name + '_item' + renderParent);
        renderParent = aThisMenu[0]._parent.pid;
      }
    }
    while(!finished);
    this._element.innerHTML = aMenu.join('');
    
    while(aSelect.length > 0)    
      document.getElementById(aSelect.pop()).className = 'selectedItem';
  },
  
  _clickMenu: function(event)
  {
    var eItem = Event.element(event);
    
    if (eItem.id.substr(this._itemOffset, 4) != 'item')
      return;

    var id = eItem.id.substr(this._itemOffset + 4);
    var newItem = this._getElement(id);
    
    if (this._selectedItem)
    {
      //Selected the selected
      if (this._selectedItem == newItem)
      {
        //alert("!1");
        return;
      }
      if (this._selectedItem.pid == newItem.id)
      {
        this._fireSelect();
        return;
      }

      //A new item was selected
      if ((newItem.pid == this._selectedItem.id) && !newItem._hasChildren)
      {
        //document.getElementById(this._name + '_item' + this._selectedItem.id).className = '';
        this._selectedItem = newItem;
        document.getElementById(eItem.id).className = 'selectedItem';
        this._fireSelect();
        return;
      }
      if ((this._selectedItem.pid == newItem.pid) &&
          !this._selectedItem._hasChildren &&
          !newItem._hasChildren)
      {
        document.getElementById(this._name + '_item' + this._selectedItem.id).className = '';
        this._selectedItem = newItem;
        document.getElementById(eItem.id).className = 'selectedItem';
        this._fireSelect();
        return;
      }
      
      this._appearFrom = 0;
      if (newItem.pid == this._selectedItem.pid)
      {
        //If there are children hide them
        if (this._selectedItem._hasChildren)
          this._aHideStack.push(this._name + '_level' + this._selectedItem.id);
          
        this._appearFrom = this._selectedItem.pid;
        
      }
      else
      {
        if (newItem._hasChildren && (newItem.pid == this._selectedItem.id))
        {
          this._appearFrom = this._selectedItem.id;
        }
        else
        {
          if (this._selectedItem._parent && (this._selectedItem._parent.pid == newItem.pid))
          {
            this._aHideStack.push(this._name + '_level' + this._selectedItem.pid);
            this._appearFrom = this._selectedItem._parent.pid;
          }
          else
          {
            var item = this._selectedItem;
            while(item.pid != 0)
            {
              this._appearFrom = item.pid;
              this._aHideStack.push(this._name + '_level' + this._appearFrom);
              item = item._parent;
            }
          }
        }
      }
    }
    this._selectedItem = this._getElement(id);

    this._fireSelect();
      
    this.refresh();
  },

  _fireSelect: function()
  {
    if (this._options.onSelect != null)
      eval(this._options.onSelect + '(\'' + this._selectedItem.id + '\')');
  },
  
  _getElement: function(id)
  {
    for (var i=0; i<this._aItems.length; ++i)
      if (this._aItems[i].id == id)
        return this._aItems[i];
        
    return null;
  },
  
  getSelected: function()
  {
    return this._selectedItem.id;
  },
  
  removeAll: function()
  {
    this._aItems.length       = 0;    
    this._aAppearStack.length = 0;
    this._aHideStack.length   = 0;
    this._selectedItem        = null;
    this._appearFrom          = 0;
  },
  
  runWithSelected: function(fnc)
  {
    var action = '';
    var idx = 0;
    while (arguments[++idx])
    {
      action += ',';
      action += '\'' + arguments[idx] + '\'';
    }
    eval(fnc + '(\'' + this._selectedItem.id + '\'' + action + ')');
  }
};
