
var plMenuSystem = Class.create();
plMenuSystem.prototype = {

    initialize: function() {

        this.hideDelay = 400;
        this.showOnMouseOver = true;

        this.menus = new Array();
        this.visibleMenu = null;
        this.id = "plMenuSystem";

        this.lastEvent = null;

        this.showEffect = null;
        this.hideEffect = null;

        this.hiding = new Array();
    },

    activate: function(isLeft) {
        if (isLeft) {
            for (i = 0; i < this.menus.length; i++)
                setupLeftMenu(this.menus[i]);
        }
        var me = this;
        this.menus.each(function(m) { m.activate(me); });

        document.onclick = this.eventHandler.bindAsEventListener(this);
    },

    addMenu: function(mnu) {
        this.menus[this.menus.length] = mnu;
    },

    setEvent: function(evt) {
        this.lastEvent = evt;
    },

    findVisibleMenu: function() {
        this.visibleMenu = this.menus.find(function(m) { return m.visible; });
    },

    checkMenuTree: function(noDelay) {
        this.dOut();
        if (noDelay) {
            this.hiding.each(function(obj) { obj.hideMenu(true); });
            this.hiding = new Array();
        }

        var e = this.lastEvent;
        var toElem;
        if (e) {
            toElem = getToElement(e);

            if (toElem) {
                var revive = this.hiding.find(function(obj) { return (isOrContains(obj.menuObj, toElem)); });
                if (revive) {
                    this.dropHider(revive);
                    revive.showMenu();
                }
            }
        }


        this.findVisibleMenu();
        if (this.visibleMenu) this.visibleMenu.checkMenu(noDelay);
    },

    eventHandler: function(evt) {
        this.setEvent(Object.extend(new Object(), evt));
        this.checkMenuTree(true);
    },

    addHider: function(obj) {
        if (!this.hiding.include(obj)) this.hiding[this.hiding.length] = obj;
    },

    dropHider: function(obj) {
        this.hiding = this.hiding.reject(function(o) { return o == obj; })
    },

    dOut: function() {
        /*		var o = '';
		
		if (arguments.length == 0) $('dTxt').value = '';	
		
		for (var i = 0; i < arguments.length; i++) {
        o += arguments[i] + '\t';
        }
        $('dTxt').value = o + '\n' + $('dTxt').value;			
        */
    }

};

var plMenu = Class.create();
plMenu.prototype = {

    initialize: function(obj, trigger, direction, offset, selectedClassName) {
        this.menuObj = $(obj);
        this.trigger = $(trigger);
        this.direction = direction; // 0-down 1-left  -->>?? 2-up 3-right
        this.trigger.menu = this;

        this.onShowMenu = null;
        this.onHideMenu = null;

        this.menuObjMouseOver = null;
        this.menuObjMouseOut = null;
        this.triggerMouseOver = null;
        this.triggerMouseOut = null;

        this.visible = false;
        this.hiding = 3; // -1 = show effect transistion; 0 = visible; 1 = delay before hide; 2 = hide effect transition; 3 = hidden
        this.hideTimer = null;
        this.showOnHide = false;
        this.hideOnShow = false;

        this.subMenus = new Array();
        this.menuSystem = null;

        if (offset == null)
            this.offset = { x: 0, y: 0 };
        else
            this.offset = offset;

        if (selectedClassName != null) {
            this.onShowMenu = function() { Element.addClassName(this.trigger, 'menuSelected'); }
            this.onHideMenu = function() { Element.removeClassName(this.trigger, 'menuSelected'); }
        }
    },

    activate: function(mnuSys) {
        this.menuSystem = mnuSys;
        this.menuObj.style.display = 'none';
        this.trigger.onclick = this.showMenu.bindAsEventListener(this);

        if ((!this.triggerMouseOver) && (this.trigger.onmouseover)) this.triggerMouseOver = this.trigger.onmouseover;
        this.trigger.onmouseover = this.mouseOverTrigger.bindAsEventListener(this);
        this.menuObj.onmouseover = this.mouseOverMenu.bindAsEventListener(this);


        if ((!this.menuObjMouseOut) && (this.menuObj.onmouseout)) this.menuObjMouseOut = this.menuObj.onmouseout;
        if ((!this.triggerMouseOut) && (this.trigger.onmouseout)) this.triggerMouseOut = this.trigger.onmouseout;

        this.subMenus.each(function(s) { s.activate(mnuSys); });
    },

    addSubMenu: function(subMnu) {
        this.subMenus[this.subMenus.length] = subMnu;
    },

    autoSize: function(target) {
        var t = $(target);

        this.menuObj.style.position = 'absolute';
        this.menuObj.style.top = "-5000px";
        this.menuObj.style.left = "-5000px";
        this.menuObj.style.height = "4000px";
        this.menuObj.style.width = "4000px";
        this.menuObj.style.display = "";

        this.menuObj.style.height = t.offsetHeight + "px";
        this.menuObj.style.width = t.offsetWidth + "px";
    },

    /*doDelay: function(evt){												
    if (((new Date()).getTime() - this.menuSystem.lastEventTime.getTime())>= this.menuSystem.hideDelay){
    this.menuSystem.dOut('dLay','fire');
    this.menuSystem.checkMenuTree();				
    }else this.menuSystem.dOut('dLay','no');
    },*/


    checkMenu: function(noDelay) {
        var visibleSub = this.subMenus.find(function(subM) { return (subM.visible); });

        var subVis = false;
        var hide = false;
        if (visibleSub) subVis = visibleSub.checkMenu(noDelay);

        this.menuSystem.dOut(this.trigger.id);
        if (subVis) return true;

        var e = this.menuSystem.lastEvent;
        var toElem;

        if (e) {
            toElem = getToElement(e);

            if (toElem &&
				 ((!isOrContains(this.menuObj, toElem)) && (!isOrContains(this.trigger, toElem)))) {
                this.hideMenu(noDelay);
                this.menuSystem.dOut('A', this.trigger.id, toElem.innerHTML, toElem.tagName, isOrContains(this.menuObj, toElem), isOrContains(this.trigger, toElem));
            }

            else if ((!toElem) && (this.menuSystem.lastEvent.pageX)) {

                var lastX = Event.pointerX(this.menuSystem.lastEvent);
                var lastY = Event.pointerY(this.menuSystem.lastEvent);

                if (
						(!Position.within(this.menuObj, lastX, lastY))
					&& (!Position.within(this.trigger, lastX, lastY))
					) {
                    this.hideMenu(noDelay);
                    this.menuSystem.dOut('B');
                }
            }
        }

        return this.visible;
    },

    mouseOutMenu: function(evt) {

        this.menuSystem.dOut('mOutM', (evt.srcElement) ? evt.srcElement.id + evt.srcElement.tagName : 'null');
        this.menuSystem.setEvent(Object.extend(new Object(), evt));

        if (this.menuObjMouseOut) this.menuObjMouseOut.call(this.menuObj, evt);

        //window.setTimeout(this.doDelay.bindAsEventListener(this),this.menuSystem.hideDelay);
        //if (this.menuSystem.showOnMouseOver) 
        this.menuSystem.checkMenuTree();
    },

    mouseOutTrigger: function(evt) {

        this.menuSystem.dOut('mOutT', (evt.srcElement) ? evt.srcElement.id + evt.srcElement.tagName : 'null');
        this.menuSystem.setEvent(Object.extend(new Object(), evt));

        if (this.triggerMouseOut) this.triggerMouseOut.call(this.trigger, evt);

        //window.setTimeout(this.doDelay.bindAsEventListener(this),this.menuSystem.hideDelay);
        if (this.menuSystem.showOnMouseOver) this.menuSystem.checkMenuTree();
    },

    mouseOverMenu: function(evt) {
        if (this.hiding == 2) { return; }

        this.menuSystem.dOut('mOver', (evt.srcElement) ? evt.srcElement.id + evt.srcElement.tagName : 'null', (evt.pageY ? evt.pageY : '0'));
        this.menuSystem.setEvent(Object.extend(new Object(), evt));

        //window.setTimeout(this.doDelay.bindAsEventListener(this),this.menuSystem.hideDelay);
        this.menuSystem.checkMenuTree();
    },

    mouseOverTrigger: function(evt) {

        this.menuSystem.dOut('sOMO', (evt.srcElement) ? evt.srcElement.id + evt.srcElement.tagName : 'null');
        this.menuSystem.setEvent(Object.extend(new Object(), evt));

        if (this.triggerMouseOver) this.triggerMouseOver.call(this.trigger, evt);

        if ((!this.visible) && ((this.menuSystem.visibleMenu) || (this.menuSystem.showOnMouseOver)))
            this.showMenu(evt);
        /*else
        this.hideOnShow = false;*/
    },

    setForSubMenus: function(prop, value) {
        this.subMenus.each(
			function(item, idx) {
			    item[prop] = value;
			    item.setForSubMenus(prop, value);
			}
		);
    },

    showMenu: function(evt) {

        var pos = Position.cumulativeOffset(this.trigger);
        var h = this.trigger.offsetHeight;
        var w = this.trigger.offsetWidth;
        var toElem;
        var inMenu = false;

        this.hideOnShow = false;

        if (evt) this.menuSystem.setEvent(Object.extend(new Object(), evt));
        toElem = getToElement(this.menuSystem.lastEvent);
        inMenu = ((toElem) && (isOrContains(this.menuObj, toElem)));


        if (this.hiding == 2) {
            if (!inMenu) this.showOnHide = true;
            return;
        }

        if (this.hideTimer) window.clearTimeout(this.hideTimer);
        this.hideTimer = null;

        this.menuSystem.dropHider(this);

        if ((this.hiding == 1) && (inMenu)) {
            this.visible = true;
        }

        this.hiding = -1;

        this.menuSystem.checkMenuTree(true);

        var leftOffset = 0;
        if (browser.ie) {
            leftOffset = 5;
        }

        if (this.direction == 0) {
            Element.setStyle(this.menuObj, { top: pos[1] + h + this.offset.y - 3 + 'px', left: pos[0] + this.offset.x - 3 + 'px' });
        } else if (this.direction == 1) {
            Element.setStyle(this.menuObj, { top: pos[1] + this.offset.y + 'px', left: pos[0] + w + this.offset.x - leftOffset + 'px' });
        }

        this.visible = true;
        if (this.menuSystem.showEffect)
            this.menuSystem.showEffect(this.menuObj, this.showFinal.bindAsEventListener(this));
        else {
            Element.setStyle(this.menuObj, { display: 'inline' });
            this.showFinal();
        }

        this.menuSystem.findVisibleMenu();

        this.menuObj.onmouseout = this.mouseOutMenu.bindAsEventListener(this);
        this.trigger.onmouseout = this.mouseOutTrigger.bindAsEventListener(this);
        if (this.onShowMenu) this.onShowMenu.call(this);


    },

    hideMenu: function(noDelay) {

        this.showOnHide = false;

        if (this.hiding == -1) {
            this.hideOnShow = true;
            return;
        }

        this.visible = false;
        this.hiding = 1;

        if (this.hideTimer) {
            window.clearTimeout(this.hideTimer);
            this.hideTimer = null;
        }

        if (noDelay) {
            /*if (this.menuSystem.hideEffect)
            this.menuSystem.hideEffect(this.menuObj,this.hideFinal.bindAsEventListener(this));
            else{*/
            Element.setStyle(this.menuObj, { display: 'none' });
            this.hideFinal();
            //}
        } else {
            this.hideTimer = window.setTimeout(this.hideStart.bindAsEventListener(this), this.menuSystem.hideDelay);
            this.menuSystem.addHider(this);
        }

        this.menuObj.onmouseout = this.menuObjMouseOut;
        this.trigger.onmouseout = this.triggerMouseOut;
        if (this.onHideMenu) this.onHideMenu();

        this.menuSystem.findVisibleMenu();
    },

    hideStart: function(evt) {
        if ((!this.visible) && (this.hiding == 1)) {  //(this.menuSystem.hiding.include(this))){

            this.hiding = 2;
            if (this.menuSystem.hideEffect)
                this.menuSystem.hideEffect(this.menuObj, this.hideFinal.bindAsEventListener(this));
            else {
                Element.setStyle(this.menuObj, { display: 'none' });
                this.hideFinal();
            }
        }
    },

    hideFinal: function() {
        this.hiding = 3;
        this.menuSystem.dropHider(this);
        if (this.showOnHide) this.showMenu();
    },

    showFinal: function() {
        this.hiding = 0;
        if (this.hideOnShow) this.hideMenu(true);
    }

};


function ShowObj(obj, rec) {
    var o = '';
    if (!rec) rec = 0;

    for (property in obj) {
        if (typeof obj[property] == 'object') {
            if (rec > 0)
                o += '[' + property + ' ' + '\n  ' + ShowObj(obj[property], rec - 1).replace(/[\n]/g, '\n  ') + ']\n';
            else
                o += '[' + property + ' ' + (obj[property] ? (obj[property].toString ? obj[property].toString() : '[object]') : 'null') + ']\n';  //'\n' + ShowObj(obj[property]).replace('\n','  \n') + ']\n';
        } else
            o += property + ' : ' + (obj[property] ? obj[property].toString() : 'undefined') + '\n';
    }
    return o;
}


function getToElement(e) {
    var toElem;

    if (e.toElement) toElem = e.toElement;
    if ((!toElem) && (e.type && (e.type == 'mouseout')) && (e.relatedTarget))
        toElem = e.relatedTarget;
    if ((!toElem) && (e.target)) toElem = e.target;
    if ((!toElem) && (e.srcElement)) toElem = e.srcElement;
    if (!e.toElement) e.toElement = toElem;

    return toElem;
}

function contains(obj1, obj2) {
    if (obj1 == obj2) return true;
    if (!obj2.parentElement) return false;
    if (obj2 == obj2.parentElement) return false;

    return contains(obj1, obj2.parentElement);
}

function isOrContains(obj1, obj2) {
    if (obj1 == obj2) return true;

    element = $(obj2), ancestor = $(obj1);
    while (element = element.parentNode)
        if (element == ancestor) return true;
    return false;
}

var AreaToReset = null;
var prevListTop = 0;
var prevObj = null;
var prevObjTop = 0;
var prevParentHeight = 0;
var smoothRunning = false;
var smoothDelayFunc = null;
var bottomMenu;  // This needs to be set correctly
var OFFSET_FROM_BOTTOM_MENU = 80;
var bottom;

function menuItem_OnClick(obj) {
    var subM = $(obj.getElementsByTagName('div')[0]);
    var p = $(obj.parentNode);
    var listArea = $(p.parentNode);
    var siblings = p.immediateDescendants();
    var subContent = obj.getElementsByClassName('subMenu')[0];
    var mT = Position.cumulativeOffset(listArea)[1];
    if (AreaToReset == p) {
        SmoothResetMenus();
        return;
    }
    AreaToReset = p;
    p.style.height = p.offsetHeight.toString() + "px";
    Position.absolutize(obj);
    for (var i = 0; i < siblings.length; i++) {
        if (siblings[i] != obj)
            siblings[i].style.display = 'none';
    }
    var showContent = function() {
        subContent.style.display = 'block';
        obj.style.height = "379px";
    }
    prevListTop = mT;
    prevObj = obj;
    prevObjTop = obj.offsetTop;
    prevParentHeight = p.offsetHeight;
    var yOffset = 360 - mT;
    var yOffset2 = 10 - prevObjTop;
    new Effect.Morph(p, { style: { height: '200px'} });
    new Effect.Move(listArea, { x: 0, y: yOffset }, { duration: 1.0 });
    new Effect.Move(obj, { x: 0, y: yOffset2, afterFinish: showContent });
}
function SmoothResetMenus() {
    if (!AreaToReset) return;
    if (smoothRunning) return;
    smoothRunning = true;
    var func1 = function() {
        if (!AreaToReset) return;
        smoothRunning = false;
        ResetMenus();
        //alert(1);
    }
    var p = $(AreaToReset);
    var listArea = $(p.parentNode);
    var subContent = prevObj.getElementsByClassName('subMenu')[0];
    subContent.style.display = '';
    prevObj.style.height = '50px';
    var yOffset = prevListTop - 360;
    var yOffset2 = prevObjTop - 10;
    new Effect.Morph(p, { style: { height: prevParentHeight.toString() + 'px'} });
    new Effect.Move(listArea, { x: 0, y: yOffset }, { duration: 1.0 });
    new Effect.Move(prevObj, { x: 0, y: yOffset2, afterFinish: func1 });
    prevObj.style.height = '';
}
function ResetMenus() {
    if (!AreaToReset) return;
    if (smoothRunning) {
        return;
    }
    var p = $(AreaToReset);
    var listArea = $(p.parentNode);
    var siblings = p.getElementsByTagName('div');
    for (var i = 0; i < siblings.length; i++) {
        siblings[i].style.display = '';
        siblings[i].style.height = '';
        siblings[i].style.position = '';
    }
    p.style.height = '';
    listArea.style.top = prevListTop.toString() + "px";
    AreaToReset = null;
}
function postSetup(mnu) {
    Position.absolutize(mnu.trigger);
}
function setupLeftMenu(mnu) {
    mnu.onShowMenu = function() {
        this.trigger.className = 'Selected';
        if (!this.trigger.longWidth) this.trigger.longWidth = this.trigger.offsetWidth + 5;
        this.trigger.style.width = this.trigger.longWidth.toString() + "px";
        this.offset = { x: -5, y: 0 };
        var oH = Element.getHeight(this.menuObj);
        var mH = Element.getHeight(this.trigger);
        var mT = Position.cumulativeOffset(mnu.trigger)[1];
        bottomMenu = leftMenu.menus[leftMenu.menus.length - 1];
        bottom = Position.cumulativeOffset(bottomMenu.trigger)[1] + OFFSET_FROM_BOTTOM_MENU;
        var yOffset = bottom - (mT + oH);
        if (yOffset > -7) yOffset = -7;
        //lll;
        this.menuObj.style.top = (this.menuObj.offsetTop + yOffset).toString() + "px";
    };
    mnu.onHideMenu = function() { this.trigger.className = 'NotSelected'; this.trigger.style.width = ""; ResetMenus(); this.offset = { x: 0, y: 0 }; };
    mnu.offset = { x: 0, y: 0 };
}

