// Constructor for Merlin menus
function MerlinMenu() {
	// The bound button element
	this.buttonElement = null;
	// The bound panel element
	this.panelElement = null;
	// Should the button image be swapped?
	this.swapButton = true;
	// Should item images be swapped?
	this.swapItems = true;
}

// Menu button ImageSwapper states
MerlinMenu.buttonSwapStates = {closed: '', open: '_o'};
// Menu item ImageSwapper states
MerlinMenu.itemSwapStates = {out: '', over: '_o'};
// Time in milliseconds after which menus are hidden
MerlinMenu.hideTimeout = 500;
// Id from setTimeout() used for hiding the active menu
MerlinMenu.hideTimeoutId = null;
// The active menu
MerlinMenu.active = null;

// Hide the active menu immediately
MerlinMenu.hide =
function () {
	var active = this.active;
	if (active) active.hide();
}

// Hide the active menu after MerlinMenus.hideTimeout milliseconds
MerlinMenu.beginHide =
function () {
	this.cancelHide();
	this.hideTimeoutId = window.setTimeout(
		"MerlinMenu.hide()",
		this.hideTimeout
	);
}

// Cancel a hide timeout started with MerlinMenu.beginHide()
MerlinMenu.cancelHide =
function () {
	if (this.hideTimeoutId) {
		window.clearTimeout(this.hideTimeoutId);
		this.hideTimeoutId = null;
	}
}

// Bind the menu button element
MerlinMenu.prototype.bindButton =
function (element) {
	element.menu = this;
	element.onmouseover = MerlinMenu.button_onMouseOver;
	element.onmouseout = MerlinMenu.button_onMouseOut;
	
	if (this.swapButton) {
		element.swapper = new ImageSwapper(element);
		element.swapper.createSuffixStates(MerlinMenu.buttonSwapStates);
	}
	
	this.buttonElement = element;
}

// Bind the menu button element using its id
MerlinMenu.prototype.bindButtonById =
function (document, id) {
	this.bindButton(document.getElementById(id));
}

// Bind the menu panel element
MerlinMenu.prototype.bindPanel =
function (element) {
	element.onmouseover = MerlinMenu.panel_onMouseOver;
	element.onmouseout = MerlinMenu.panel_onMouseOut;
	this.panelElement = element;
}

// Bind the menu panel element using its id
MerlinMenu.prototype.bindPanelById =
function (document, id) {
	this.bindPanel(document.getElementById(id));
}

// Bind a menu item element
MerlinMenu.prototype.bindItem =
function (element) {
	element.menu = this;
	element.onmouseover = MerlinMenu.item_onMouseOver;
	element.onmouseout = MerlinMenu.item_onMouseOut;
	
	if (this.swapItems) {
		element.swapper = new ImageSwapper(element);
		element.swapper.createSuffixStates(MerlinMenu.itemSwapStates);
	}
}

// Bind a menu item element using its id
MerlinMenu.prototype.bindItemById =
function (document, id) {
	this.bindItem(document.getElementById(id));
}

// Open the menu
MerlinMenu.prototype.show =
function () {
	if (this.panelElement) {
		MerlinMenu.hide();
		this.panelElement.style.visibility = 'visible';
		if (this.swapButton) this.buttonElement.swapper.swap('open');
		MerlinMenu.active = this;
	}
}

// Close the menu
MerlinMenu.prototype.hide =
function () {
	if (this.panelElement) {
		this.panelElement.style.visibility = 'hidden';
		if (this.swapButton) this.buttonElement.swapper.swap('closed');
		MerlinMenu.active = null;
	}
}

// mouseOver event handler for the button element
MerlinMenu.button_onMouseOver =
function () {
	this.menu.show();
}

// mouseOut event handler for the button element
MerlinMenu.button_onMouseOut =
function () {
	MerlinMenu.beginHide();
}

// mouseOver event handler for the panel element
MerlinMenu.panel_onMouseOver =
function () {
	MerlinMenu.cancelHide();
}

// mouseOut event handler for the panel element
MerlinMenu.panel_onMouseOut =
function () {
	MerlinMenu.beginHide();
}

// mouseOver event handler for item elements
MerlinMenu.item_onMouseOver =
function () {
	if (this.menu.swapItems) this.swapper.swap('over');
}

// mouseOut event handler for item elements
MerlinMenu.item_onMouseOut =
function () {
	if (this.menu.swapItems) this.swapper.swap('out');
}
