isys.controls.MenuState = [];


isys.controls.Menu = function(loadFrom) {
    this.m_root = new isysMenuItem("___root");
    this.m_root.m_menu = this;
    this.items = this.m_root;
    this.onpopup = null;
    this.onhide = null;
    if (typeof(loadFrom) == "object")
        this.load(loadFrom);
};

function isysMenuItem(caption) {
    this.m_items = [];
    this.caption = caption;
	isys.events.register(this);
};

isys.controls.Menu.prototype = {
    m_root: null,
    m_gutterWidth: 40,
    m_ready: false,
    m_popup: false,
    m_popupStart: null,
    expandTimeout: 550, 
    hideTimeout: 150,  
    m_spacing: 15, 
    items: null,
    onpopup: null,
    maxWidth: 600,
    onitem: null,
    
    prepare: function(dest) {
        if (!this.m_ready) {
            var holder = isys.createElement("div", dest);
            this.m_root._makeSubDiv(holder);
            holder.style.display = "inline";
            this.m_ready = true;
        }
    },
    
    popup: function(x, y) {
		if (typeof(isys.controls.MenuState.popup) == "object")
			isys.controls.MenuState.popup.hide();
		isys.controls.MenuState.popup = this;
        this.prepare(document.body);
        this.m_root.popup(x, y);
        isys.setCapture(this);
        this.m_popupStart = new Date();
        if (this.onpopup)
            this.onpopup(this);
    },
    popupHere: function(e) {
    	var pos = isys.getPos(e);
		this.popup(pos.left, pos.bottom);
    },
    hide: function() {
        isys.releaseCapture(this);
        this.m_root.hide();
        if (this.onhide)
            this.onhide(this);
    },
    
    onmousedown: function(event) {
        if (new Date() - this.m_popupStart > 15)
            this.hide();
    },
    
    load: function(src) {
		isys.debug.log("loading");
		if (typeof(src) == "string")
			src = document.getElementById(src);
        if (typeof(src) == "undefined")
            return;
        
        if (typeof(src.length) == "undefined")
			this._sync(new isys.xml.node(src).firstChild(), this.m_root, 0);
		else
			this._syncArray(src, this.m_root, 0);
    },
    
    onclick: function(item) {	
		if (this.onitem)
			this.onitem(item);
		else if (typeof(item.href) == "string")
		{
			if (item.href.indexOf("javascript:") == 0)
				window.setTimeout(item.href.substr(11), 5);
			else
				window.location = item.href;
		} else if(typeof(item.href) == "function")
			item.href();
    },
    
    _syncArray: function(src, dest, level) {
		for (var i = 0; i < src.length; i++) {
			var menu = src[i];
			if (typeof(menu.visible) == "undefined" || menu.visible) {
				var item = dest.add(menu.caption);
				item.description = menu.description;
				item.image = menu.image;
				item.href = menu.href;
				item.def = menu.def;
				if (typeof(menu.items) != "undefined")
					this._syncArray(menu.items, item, level+1);
			}
		}
    },
    
    _sync: function(node, dest, level) {
        var c = node.firstChild();
        while (c) {
			//isys.debug.log("sync: " + c.getNodeName());
            if (c.getNodeName() == "ITEM" || c.getNodeName() == "SPAN") {
                var item = dest.add(c.getAttribute("caption"));
                item.description = c.getAttribute("description");
                item.image = c.getAttribute("img");
                item.href = c.getAttribute("href");
                this._sync(c, item, level+1);
            }
            c = c.nextSibling();
        }
    },
    
    add: function(caption, action, image) {
		var retVal = this.m_root.add(caption);
		retVal.image = image;
		retVal.href = action;
		return retVal;
	},
	
	renderTo: function(dest) {
		this.prepare(document.body);
		var me = this;
		var tb = new isys.controls.Toolbar();
		for (var i = 0; i < this.m_root.m_items.length; i++) {
			tb.add(new isys.controls.Toolbar.Button(this.m_root.m_items[i].caption, "", function(e) {
				isys.setCapture(me);
				me.m_popupStart = new Date();
				var pos = isys.getPos(e.div);
				e._mnu.popup(pos.left, pos.bottom);
			}, null))._mnu = this.m_root.m_items[i];
		}
		tb.renderTo(dest);
	}
};

isysMenuItem.prototype = {
    m_items: [],
    m_parent: null,
    m_menu: null,
    m_minWidth: 0,
    m_subMenu: null,
    m_div: null,
    m_selected: null,
    m_expandTimer: -1,
    m_visible: false,
    m_fadeTimer: -1,
    caption: "",
    description: "",
    href: null,
    m_isSelected: false,
    m_level: 0,
    
    dispose: function() {
		this.m_items = null;
		this.m_parent = null;
		this.m_menu = null;
		this.m_subMenu = null;
		this.m_div = null;
		this.m_selected = null;
    },    
    
    add: function(caption, action, image) {
        var retVal = new isysMenuItem(caption);
        this.m_items[this.m_items.length] = retVal;
        retVal.m_parent = this;
        retVal.m_menu = this.m_menu;
        retVal.m_level = this.m_level + 1;
		retVal.image = image;
		retVal.href = action;
        return retVal;
    },
    
    hasChildren: function() {
        return this.m_items.length > 0;
    },
    
    expandMenu: function() {
        isys.debug.log("expandMenu: " + this.caption + "; " + this.m_level);
        if (!this.m_visible) {
            var x = this.m_div.offsetLeft + this.m_div.offsetWidth;
            var y = this.m_div.offsetTop;
            var pos = isys.getPosition(this.m_div);
            pos[0] += this.m_div.offsetWidth + 1;
            
            this.popup(pos[0], pos[1]);
        }
    },
    
    popup: function(x, y) {
		isys.debug.log("popup menu: " + this.m_items.length);
        if (this.m_subMenu.offsetParent == null)
            document.body.appendChild(this.m_subMenu);
        this.m_subMenu.style.display = "none";
        this.m_subMenu.style.position = "absolute";
        this.m_subMenu.style.left = x + "px";
        this.m_subMenu.style.top = y + "px";
        this.m_subMenu.style.display = "inline";
        this.m_visible = true;
        
        var pos = isys.getPos(this.m_subMenu);
        if (pos.right > document.body.clientWidth) {
			if (this.m_parent == null)
				this.m_subMenu.style.left = x - (pos.right - document.body.clientWidth) + "px";
			else {
				this.m_subMenu.style.left = this.m_parent.m_subMenu.offsetLeft - pos.width + "px";
			}
		}
		
		if (document.documentElement && typeof(window.opera) == "undefined")
			if (pos.bottom > isys.getViewportHeight()) 
				this.m_subMenu.style.top = y - (pos.bottom - isys.getViewportHeight()) + "px";	
	
        isys.debug.log("Popup: " + this.caption + "; " + this.m_level + "; x: " + x + "; y: " + y);
    },
    
    hide: function() {
        if (this.m_visible) {
            if (this.m_expandTimer != -1)
                window.clearTimeout(this.m_expandTimer);
            if (this.m_fadeTimer != -1)
                window.clearInterval(this.m_fadeTimer);

            this.m_fadeTimer = -1;
            this.m_expandTimer = -1;
            if (this.m_subMenu) {
                this.m_subMenu.style.display = "none";
            }
        }
        //this.m_isSelected = false;
        this.m_visible = false;
        for (var i = 0; i < this.m_items.length; i++) {
            this.m_items[i].m_div.className = "isysMenuItem " + (this.m_items[i].hasChildren()?" isysMenuItemExpand":"");
            this.m_items[i].m_isSelected = false;
            this.m_items[i].hide();
        }
    },    
    
    select: function() {
        if (!this.m_isSelected) {
            isys.debug.log("select: " + this.caption + "; " + this.m_level);
            this.m_div.className = "isysMenuItemOver " + (this.hasChildren()?" isysMenuItemExpand":"");
            this.m_isSelected = true;
            this.m_parent.setSelected(this);
            if (this.hasChildren()) 
                this._setExpandTimer();
        }
    },
    
    deselect: function(force) {
        isys.debug.log("deselect: " + this.caption + "; " + this.m_level);
        
        this.m_div.className = "isysMenuItem " + (this.hasChildren()?" isysMenuItemExpand":"");  
        this.m_isSelected = false;
        if (force) 
            this.hide();
        else
            this._setHideTimer();
        
        if (this.m_expandTimer != -1)
            window.clearTimeout(this.m_expandTimer);
    },
    
    setSelected: function(item) {
        isys.debug.log("setSelected: " + item.caption + "; " + item.m_level);
        for (var i = 0; i < this.m_items.length; i++)
            if (this.m_items[i] != item)
                this.m_items[i].deselect();
                
        this.m_selected = item;
        if (this.m_selected) {
        
        }
    },
    
    _create: function(typ, dest) {
        var retVal = document.createElement(typ);
        if (dest)
            dest.appendChild(retVal);
        return retVal;
    },
    
    _float: function(e, value) {
        if (typeof(e.style.cssFloat) != "undefined")
            e.style.cssFloat = value;
        else
            e.style.styleFloat = value;
    },
    
    _setExpandTimer: function() {
        var self = this;
        proc = function() {
            isys.debug.log("IN _setExpandTimer: " + self.caption + "; " + self.m_isSelected);
            if (self.m_isSelected && self.m_parent.m_visible)
                self.expandMenu();
        };
        this.m_expandTimer = window.setTimeout(proc, this.m_menu.expandTimeout);
        isys.debug.log("_setExpandTimer: " + this.caption + "; " + this.m_level + "; " + this.m_expandTimer);

    },
    
    _setHideTimer: function() {
        var self = this;
        f = function() {
            self.hide();
        };
        this.m_hideTimer = window.setTimeout(f, this.m_menu.hideTimeout);
    },
    
    _hookEvents: function() {
        var self = this;
        var clsSuffix = (this.hasChildren()?" isysMenuItemExpand":"");

		isys.events.attachEvent(self.m_div, "mouseover", function(e) {
				self.select();
			});
        isys.events.attachEvent(self.m_div, "mousedown", function(e) {
				if (!e) e = window.event;
				if (typeof(self.onclick) != "undefined")
					self.onclick(self);
				else if (typeof(self.m_menu.onclick)  != "undefined")
					self.m_menu.onclick(self);
				if (self.m_items.length == 0)
					self.m_menu.hide();
				else
					self.expandMenu();
				e.cancelBubble = true;
			});
        isys.events.attachEvent(self.m_div, "mousemove", function(e) {
				if (!e) e = window.event;
				e.cancelBubble = true;
			});
    },
    
    _hookMenuEvents: function() {
        var self = this;
        isys.events.attachEvent(this.m_subMenu, "mouseover", function(e) {
				if (self.m_hideTimer)
					window.clearTimeout(self.m_hideTimer);
			});
    },
    
    _renderTo: function(dest) {
        var clsSuffix = (this.hasChildren()?" isysMenuItemExpand":"");
        var div = this._create("div", dest);
        div.className = "isysMenuItem" + clsSuffix;
        div.style.zIndex = 100;
        div.style.position = "relative";
        this.m_div = div;

        var body = this._create("div", div);
        body.className = "isysMenuItemBody";
        body.style.marginLeft = (this.m_menu.m_gutterWidth + 4) + "px";
        body.style.marginRight = "10px";

        if (this.caption == "-") {
            var div = this._create("div", body);
            div.className = "isysMenuSeperator";
        } else {
            var caption = this._create("div", body);
            caption.className = "isysMenuItemCaption";
            if (this.def)
				caption.style.fontWeight = "bold";
            caption.innerHTML = this.caption;
            
            var desc = this._create("div", body);
            desc.className = "isysMenuItemDescription";
            if (this.description)
                desc.innerHTML = this.description;

            if (this.image) {            
                var image = this._create("div", div);
                image.className = "isysMenuItemImage";
                try {
                    image.style.backgroundImage = "url(" + this.image + ")";
                } catch(e) {}
            } else if (this.checked) {
                var image = this._create("div", div);
                image.className = "isysMenuItemChecked";
            }
            
            var captionMet = isys.textMetrics(this.caption, caption);
            var descMet = isys.textMetrics(this.description, desc);
            var captionWidth = captionMet[0];
            var descWidth = descMet[0]; 
            
            var br = this._create("div", div);
            br.style.clear = "both";
           
            var w = captionWidth;
            if (descWidth > captionWidth) {
                w = descWidth; //captionWidth + (descWidth - captionWidth) / 2;
            }
            if (w > this.m_menu.maxWidth)
				w = this.m_menu.maxWidth;
            this.m_minWidth = (w + this.m_menu.m_gutterWidth + 4) + 15 + this.m_menu.m_spacing;
            
            this._hookEvents();
        }
    },
    
    getMinWidth: function() {
        return this.m_minWidth;
    },
    
    _makeSubDiv: function(dest) {
        var div = this._create("div", dest);
        div.style.position = "absolute";
        div.style.left = "-15000px";
        div.className = "isysMenu" + (this.m_menu.m_popup?" isysMenuPopup":"");

        var gutter = this._create("div", div);
        gutter.style.position = "absolute";
        gutter.style.top = "0px";
        gutter.style.left = "0px";
        gutter.style.width = this.m_menu.m_gutterWidth + "px";
        gutter.style.zIndex = 0;
        gutter.className = "isysMenuGutter";
        
        // Shadows
        var shadowRight = isys.createElement("div", div);
        shadowRight.style.position = "absolute";
        shadowRight.style.top = "2px";
        shadowRight.className = "shadowRight";
        
        var shadowBottom = isys.createElement("div", div);
        shadowBottom.style.position = "absolute";
        shadowBottom.style.left = "2px";
        shadowBottom.className = "shadowBottom";        
        
        // Loop through and create elements
        var minWidth = 0;
        for (var i = 0; i < this.m_items.length; i++) {
            this.m_items[i]._renderTo(div);
            if (this.m_items[i].hasChildren())
                this.m_items[i]._makeSubDiv(dest);
            
            minWidth = Math.max(minWidth, this.m_items[i].getMinWidth());
        }
        
        div.style.width = minWidth + "px";
        gutter.style.height = div.clientHeight + "px";
        shadowRight.style.height = div.clientHeight + "px";
        shadowBottom.style.top = div.clientHeight + 1 + "px";
        if (minWidth > 0) {
            shadowRight.style.left = minWidth + 1 + "px";
            shadowBottom.style.width = minWidth - 1 + "px";
        }
        
        this.m_subMenu = div;
        this._hookMenuEvents();

        return div;
    }
};

isys.controls.PopupMenu = function(loadFrom) {
    var retVal = new isys.controls.Menu(loadFrom);
    retVal.m_gutterWidth = 22;
    retVal.m_popup = true;
    return retVal;
};