menuSystem = new Class({
  // menu div, main page holder, HTML Object where to display hint
  initialize: function (placeHolder, mainPage, hint) {
      this._animating = 0;    // >0 if animating taking place
      this._currentPageId=1;  // > current page index
      this._lastPageId=0      // > last page index
      this._buttonCount=1;    // number of buttons
      this.$tmp={'_hint':hint,
        '_placeholder':placeHolder,
        '_buttons':[],
        '_mainPage':mainPage};
      menu=this;
  }});

menuSystem.implement({

  buttonPressed : function(returnLast) {
    var v=this.$tmp._buttons[this._currentPageId-1];
    if (!v && returnLast)
      v=this.$tmp._buttons[this._lastPageId-1];
    return v.id;
  },

  _init : function () {
    this._initialised=true;
    this._animating = 0;
    this._currentPageId=1;
    this._lastPageId=0
    var menu=this;
    $$('div.reveal').each(
        function(el) {
          var slide=new Fx.Styles(el, {duration:900,transition:Fx.Transitions.Expo.easeOut});
          slide.addEvent("onComplete", function () {
            menu._animating--;
            if (!menu._animating)
              menu.fireEvent("onPageChange", [0,1]);
          });
          slide.addEvent("onStart", function () { menu._animating++;});

          if (el.id=='header')
            slide.start({'left': 100})
          else {
            el.style.top=el.$tmp.menu._getPos(el.index-1)+'px';
            slide.start({'left': (el.index-1)%2?650:740});
          };
        }
    ); // each
  },

  _getPos : function (a) {
    return Math.floor(a*85/2)+65;
  },

  // onMouseLeaveButton
  _mouseLeave :function(event) {
    var event = new Event(event), menu=event.target.$tmp.menu;

    if (menu._animating)
      return;
    // if not the current page
    if (event.target.index==menu._currentPageId || menu._animating)
      return;
    event.target.setOpacity(0.5);
    if (menu.$tmp._hint)
      menu.$tmp._hint.innerHTML="&nbsp;";
  },

  // onMouseEnterButton
  _mouseEnter : function(event) {
    var event = new Event(event), menu=event.target.$tmp.menu;
    if (menu._animating)
      return;
    if (event.target.index == menu._currentPageId || menu._animating)
      return;
    event.target.setOpacity(1);
    if (soundManager)
      soundManager.play("beep");
    if (menu.$tmp._hint)
      menu.$tmp._hint.innerHTML=event.target.alt;
  },

  // registers a button
  registerButton : function (imgSrc, hint) {
    var id=this.$tmp._placeholder.id+'_'+this._buttonCount;
    var el=new Element("DIV", {'class':'reveal',
                               'id':id+'_div',
                               'top':this._getPos(this._buttonCount)});
    el.$tmp.menu=this;
    el.index=this._buttonCount+1;
    var img=new Element("IMG", {'id':id+'_img',
                                'src':imgSrc,
                                'class':'faint',
                                'alt':hint});
    img.$tmp.menu=this;
    img.addEvent("mouseenter", this._mouseEnter);
    img.addEvent("mouseleave", this._mouseLeave);
    img.addEvent("click", this._click);
    img.index=this._buttonCount+1;
    img.setOpacity(0.5);
    el.inject(this.$tmp._placeholder);
    img.inject(el);
    this.$tmp._buttons[this._buttonCount++]=el;
    return el;
  },

  deleteButton : function (index) {
    this.$tmp._buttons.remove(this.$tmp._buttons[index]);
  },

  // moves all buttons to the original position
  _resetMenu : function(after, event) {
    var menu, changed=false;
    if (event)
      menu=event.target.$tmp.menu
    else
      menu=this;
    menu._lastPageId=menu._currentPageId;
    menu._currentPageId=0;
    for (var a=menu._buttonCount-1;a>0;a--) {
      var p=menu._getPos(a);
      // get DIV's child node
      var c=menu.$tmp._buttons[a];
      c.firstChild.setOpacity(0.5);
      if (c.style.top!=p+'px') {
        changed=true;
        var f=new Fx.Styles(c, {duration:1000, transition: Fx.Transitions.Expo.easeOut});
        f.addEvent("onStart", function () { menu._animating++});
        f.addEvent("onComplete", function () {
          menu._animating--;
          if (!menu._animating && $type(after)=="function")
            after(event);
          });
        f.start({'top':p,'left': a%2?650:740});
      }
    }
    if (!changed && $type(after)=="function")
      after(event);

  },

  gotoPage : function (newPage) {
     if (this._currentPageId==newPage) return;
     if (newPage==1) {
       this.reset();
     }
     else {
       var e={
        'type':'',
        'shiftKey':null,
        'ctrlKey':null,
        'altKey':null,
        'metaKey':null,
        'srcElement':this.$tmp._buttons[newPage].firstChild}
       e.target={'nodeType':1};
       e.target.$tmp={'menu':this};
       this._click(e);
       e.target=null;
       e.target.$tmp.menu=null;
     }
  },

    // onclick event
  _click : function(event) {
    var event = new Event(event), menu=event.target.$tmp.menu;
    if (menu._animating)
      return;

    if (menu._currentPageId==event.target.index)
      return;

    if (menu._currentPageId) {
      // restore menu order
      menu._resetMenu(menu._click, event);
      return;
    }

    event.target.setOpacity(1);

    // move selected one to top right corner
    var imgDiv=event.target.parentNode;
    menu._lastPageId==menu._currentPageId;
    menu._currentPageId=event.target.index;

    var selectedButton=new Fx.Styles(imgDiv, {duration:600,transition:Fx.Transitions.Expo.easeInOut});
    selectedButton.addEvent("onStart", function () {
      menu._animating++
    });
    selectedButton.addEvent("onComplete", function () {
      menu._animating--
      menu.fireEvent("onPageChange", [menu._lastPageId, menu._currentPageId]);
    });
    selectedButton.start({'top':-10, 'left':650})

    // re-shuffle order
    for (var a=parseInt(imgDiv.index)+1; a<menu._buttonCount; a+=2) {
      var t=new Fx.Styles(menu.$tmp._buttons[a], {duration:600,transition:Fx.Transitions.Expo.easeInOut});
      t.addEvent("onStart", function () { menu._animating++});
      t.addEvent("onComplete", function () { menu._animating--});
      t.start({'top':menu._getPos(a-2),'left':a%2?650:740});
      t=null;
    }
    selectedButton=null;
    event.stop;
  },

  reset: function () {
    var menu=this;
    if (!this._initialised)
      this._init();
    else
      this._resetMenu(function () {
        menu.fireEvent("onPageChange", [0, 1]);
      });
  }
});

menuSystem.implement(new Events);
