// TODO: Anchor bounds
// TODO: mouseout timeout / visibility controller
// TODO: click close / scroll close
// TODO: hookup controler
// TODO: parent scroll logic
// TODO: extract Positioning

var DropDownDirection = { 
	top : 1, bottom : 2, center : 0,
	left : 4, right : 8,
	horMask : 12, vertMask : 3,
	topLeft : 1 | 4, topCenter : 1 | 0, topRight : 1 | 8, 
	bottomLeft : 2 | 4, bottomCenter : 2 | 0, bottomRight : 2 | 8, 
	centerLeft : 0 | 4, centerCenter : 0 | 0,  centerRight : 0 | 8};
var DropDownMatch = { never : false, atLeast : 1, atMost : 2, always : true };

function DropDown(elementId, anchorId, alignment, anchorPoint) {
	if (typeof(elementId) == "string")
		this.element = document.getElementById(elementId);
	else
		this.element = elementId;
	
	this.opened = false;
	
	if (typeof(anchorId) == "string")
		this.anchor = document.getElementById(anchorId);
	else
		this.anchor = anchorId;
	
	this.shim = DropDownManager.createIEshim();
	
	if (typeof(alignment) != "undefined" && alignment != null)
		this.alignment = alignment;
	if (typeof(anchorPoint) != "undefined" && anchorPoint != null)
		this.anchorPoint = anchorPoint;
	
	DropDownManager.register(this);
}

DropDown.prototype.anchor = null;
DropDown.prototype.anchorPoint = DropDownDirection.bottomLeft;
DropDown.prototype.alignment = DropDownDirection.bottomRight;
DropDown.prototype.matchAnchorWidth  = DropDownMatch.never;
DropDown.prototype.matchAnchorHeight = DropDownMatch.never;
DropDown.prototype.leftShift = 0;
DropDown.prototype.upShift = 0;
DropDown.prototype.opened = false;
DropDown.prototype.parent = null;
DropDown.prototype.shimInitialized = false;
DropDown.prototype.shouldClose = false;
DropDown.prototype.elementRect = { left : 0, right : 0, top : 0, bottom : 0, width : 0, height : 0 };
DropDown.prototype.anchorRect = { left : 0, right : 0, top : 0, bottom : 0, width : 0, height : 0 };
DropDown.prototype.shim = null;
DropDown.prototype.childDropDown = null;

DropDown.prototype.open = function() {
	this.element.style.display = '';
	
	if (this.onopen)
		this.onopen();
	
	this.autosize();
	
	if (this.onopened)
		this.onopened();
		
	this.opened = true;
}

DropDown.prototype.autosize = function() {
	// initial location and size
	this.elementRect = lib_getLocation(this.element, true);
	this.anchorRect = lib_getLocation(this.anchor, true);
	
	
	this.matchSize();	
	this.position();
	
	if (typeof(this.shim) == "string")
		this.shim = document.getElementById(this.shim);
		
	if (this.shim) {
		
		this.shim.style.left = this.element.style.left;
		this.shim.style.top = this.element.style.top;
		this.shim.style.width = this.element.offsetWidth;
		this.shim.style.height = this.element.offsetHeight;
		this.shim.style.display = '';
		
		if (!this.shimInitialized) {
			if (this.element.style.zIndex == 'auto' || this.element.style.zIndex == '0') {
				if (this.parent != null && this.parent.element != null)
					this.element.style.zIndex = 10 + this.parent.element.style.zIndex;
				else
					this.element.style.zIndex = 500;
			}
			
			this.shim.style.zIndex = this.element.style.zIndex - 1;
			this.shimInitialized = true
		}
			
		// alert(this.shim.style.zIndex + "; " + this.shim.style.width + " x " + this.shim.style.height + "; " + this.shim.style.display)
	}
}

DropDown.prototype.position = function() {
	
	// override width
	this.elementRect.width = this.getWidth();
	// adjust right
	this.elementRect.right = this.elementRect.left + this.elementRect.width;
	// override height
	this.elementRect.height = this.getHeight();
	// adjust bottom
	this.elementRect.bottom = this.elementRect.top + this.elementRect.height;
	
	// override left
	this.elementRect.left = this.getLeft();
	// adjust right (again)
	this.elementRect.right = this.elementRect.left + this.elementRect.width;
	// override top
	this.elementRect.top = this.getTop();
	// adjust bottom (again)
	this.elementRect.bottom = this.elementRect.top + this.elementRect.height;
	
	// shift by offsets
	this.elementRect.left += this.leftShift;
	this.elementRect.top -= this.upShift;
	
	// adjust right and bottom (again!!)
	this.elementRect.right += this.leftShift;
	this.elementRect.bottom -= this.upShift;
	
	// check whether elementRect is within bounds
	var delta = 0;
	
	delta = this.elementRect.right - this.getRightBound();
	if (delta > 0) {
		this.elementRect.left -= delta;
		this.elementRect.right -= delta;
	}
	delta = this.elementRect.left - this.getLeftBound();
	if (delta < 0) {
		this.elementRect.left -= delta;
		this.elementRect.right -= delta;
	}
	delta = this.elementRect.bottom - this.getBottomBound();
	if (delta > 0) {
		this.elementRect.top -= delta;
		this.elementRect.bottom -= delta;
	}
	delta = this.elementRect.top - this.getTopBound();
	if (delta < 0) {
		this.elementRect.top -= delta;
		this.elementRect.bottom -= delta;
	}
	
	// OK. Place at correct position.
	this.element.style.left = this.elementRect.left + 'px';
	this.element.style.top = this.elementRect.top + 'px';
}

DropDown.prototype.matchSize = function() {
	if (this.anchor) {
		var changedSize = false;
		switch (this.matchAnchorWidth) {
			case DropDownMatch.atLeast:
				if (this.anchorRect.width < this.elementRect.width) {
					this.element.style.width = this.anchorRect.width + 'px';
					changedSize = true;
				}
				break;
			case DropDownMatch.atMost:
				if (this.anchorRect.width > this.elementRect.width) {
					this.element.style.width = this.anchorRect.width + 'px';
					changedSize = true;
				}
				break;
			
			case DropDownMatch.always:
				if (this.anchorRect.width != this.elementRect.width) {
					this.element.style.width = this.anchorRect.width + 'px';
					changedSize = true;
				}
				break;
		}
			
		switch (this.matchAnchorHeight) {
			case DropDownMatch.atLeast:
				if (this.anchorRect.height < this.elementRect.height) {
					this.element.style.height = this.anchorRect.height + 'px';
					changedSize = true;
				}
				break;
			case DropDownMatch.atMost:
				if (this.anchorRect.height > this.elementRect.height) {
					this.element.style.height = this.anchorRect.height + 'px';
					changedSize = true;
				}
				break;
			case DropDownMatch.always:
				if (this.anchorRect.height != this.elementRect.height) {
					this.element.style.height = this.anchorRect.height + 'px';
					changedSize = true;
				}
				break;
		}
		
		if (changedSize) {
			this.elementRect.width = this.element.offsetWidth;
			this.elementRect.height = this.element.offsetHeight;
			
			this.elementRect.right = this.elementRect.left + this.elementRect.width;
			this.elementRect.bottom = this.elementRect.top + this.elementRect.height;
		}
	}
}

DropDown.prototype.close = function() {
	if (this.opened) {
		this.element.style.display = 'none';
		if (this.shim && typeof(this.shim) != "string") {
			this.shim.style.display = 'none';
		}
		this.opened = false;
		this.shouldClose = false;
		
		if (this.onclose)
			this.onclose();
	}
	
	if (this.childDropDown)
		this.childDropDown.close();
}

DropDown.prototype.openChild = function(child) {
	if (typeof(child) == "string")
		child = document.getElementById(child);
	
	if (this.childDropDown)
		this.childDropDown.close();
	
	this.childDropDown = child;
	
	if (this.childDropDown)
		this.childDropDown.open();
}

DropDown.prototype.toggle = function() {
	if (this.opened) {
		this.close();
	} else {
		this.open();
	}
}

DropDown.prototype.getAnchorLeft = function() {
	if (this.anchor) {
		switch (this.anchorPoint & DropDownDirection.horMask) {
			case DropDownDirection.left:
				return this.anchorRect.left;
			
			case DropDownDirection.right:
				return this.anchorRect.right;

			default:
				return this.anchorRect.left + this.anchorRect.width / 2;
		}
	} else {
		return 0;
	}
}

DropDown.prototype.getAnchorTop = function() {
	if (this.anchor) {
		switch (this.anchorPoint & DropDownDirection.vertMask) {
			case DropDownDirection.top:
				return this.anchorRect.top;
			
			case DropDownDirection.bottom:
				return this.anchorRect.bottom;

			default:
				return this.anchorRect.top + this.anchorRect.height / 2;
		}
	} else {
		return 0;
	}
}

DropDown.prototype.getAnchorWidth = function() {
	if (this.anchor)
		return this.anchorRect.width;
	else
		return 0;
}

DropDown.prototype.getAnchorHeight = function() {
	if (this.anchor)
		return this.anchorRect.height;
	else
		return 0;
}

DropDown.prototype.getLeft = function() {
	var left = this.getAnchorLeft();
	var width = this.getAnchorWidth();
	var offsetWidth = this.element.offsetWidth;
	
	switch (this.alignment & DropDownDirection.horMask) {
		case DropDownDirection.left:
			return left - offsetWidth;
		case DropDownDirection.right:
			return left;
		default:
			return left + (width - offsetWidth) / 2;
	}
}

DropDown.prototype.getTop = function() {
	var top = this.getAnchorTop();
	var height = this.getAnchorHeight()
	var offsetHeight = this.element.offsetHeight;
	
	switch (this.alignment & DropDownDirection.vertMask) {
		case DropDownDirection.top:
			return top - offsetHeight;
		case DropDownDirection.bottom:
			return top;
		default:
			return top + (height - offsetHeight) / 2;
	}
}

DropDown.prototype.getWidth = function() {
	return this.elementRect.width;
}

DropDown.prototype.getHeight = function() {
	return this.elementRect.height;
}

DropDown.prototype.getLeftBound = function() {
	return 0;
}

DropDown.prototype.getRightBound = function() {
	return document.body.offsetWidth + document.body.scrollLeft;
}

DropDown.prototype.getTopBound = function() {
	return 0;
}

DropDown.prototype.getBottomBound = function() {
	return document.body.offsetHeight + this.elementRect.height + document.body.scrollTop;
}

var DropDownManager = {};
DropDownManager.registered = false;
DropDownManager.components = [];
DropDownManager.__ieshimcount = 0;

DropDownManager.register = function(dropdown) {
	DropDownManager.init();
	
	DropDownManager.components[DropDownManager.components.length] = dropdown;
		
	/*lib_addEventListner(dropdown.element, "click", 
		function() { 
			if (window.event) 
				window.event.cancelBubble = true; 
			return false; 
		});*/
	
	var anchor = dropdown.anchor;
	
	if (anchor) {
		var parent = anchor.parentNode;
	
		while (parent) {
			lib_addEventListner(parent, "scroll", 
				function() { 
					dropdown.close(); 
				});
			parent = parent.parentNode;
		}
	}
}

DropDownManager.init = function() {
	if (DropDownManager.registered)
		return;

	DropDownManager.registered = true;
		
	lib_addEventListner(document.body, "click", DropDownManager.closeAll);
	
	//if (bw.ie55up) {
		//document.write("<iframe id=\"IE55IFRAMEHACK\" style=\"display: none; position: absolute; z-index: -999;\" frameBorder=\"0\" scrolling=\"no\"></iframe>");
		
	//}
}

DropDownManager.createIEshim = function() {
	if (bw.ie55up) {
		var shimId = "IE55IFRAMESHIM_" + (DropDownManager.__ieshimcount++);
		
		document.write("</span><iframe id=\"" + shimId + "\" style=\"display: none; position: absolute; z-index: 1;progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0);\" frameBorder=\"0\" scrolling=\"no\"></iframe>");
		
		var shim = document.getElementById(shimId);
		
		if (shim)
			return shim;
		else
			return shimId;
	}
	return null;
}

DropDownManager.closeAll = function() {
	for (var i = 0; i < DropDownManager.components.length; i++) {
		var dropdown = DropDownManager.components[i];
		
		if (dropdown.opened)
			dropdown.close();
	}
}

DropDownManager.open = function(current) {
	for (var i = 0; i < DropDownManager.components.length; i++) {
		var dropdown = DropDownManager.components[i];
		
		if (dropdown.opened && dropdown != current)
			dropdown.close();
	}
	
	if (!current.opened)
		current.open();
	
	if (window.event)
		window.event.cancelBubble = true;
}

DropDownManager.toggle = function(current) {
	if (window.event)
		window.event.cancelBubble = true;
		
	for (var i = 0; i < DropDownManager.components.length; i++) {
		var dropdown = DropDownManager.components[i];
		
		if (dropdown != current)
			dropdown.close();
	}
	
	current.toggle();
}