/*
* This class handles the renderization of a item.
* An item may be a Category, a Place, a StaticInformation, or any other object
*/
function ItemHandler()
{
	this.renderItem = function(item) {}
}

/*
* This Default Item Handler renders the item using a template. Also, looks for link elements inside the div
* declaration and assigns to them a mouseclick event handler
*/
function DefaultItemHandler(template, eventHandler)
{
	this.template = template;
	this.eventHandler = eventHandler;
	
	this.getTemplate = function(item)
	{
		return this.template;
	}
	
	this.renderItem = function(item)
	{	
		var text = this.getTemplate(item).parse({item : item});
		var div = document.createElement("div");
		div.innerHTML = text;
		var links = div.getElementsByTagName("A");
		for (var i = 0; i < links.length; i++)
		{
			var link = links[i];
			link.item = item;
			link.itemFactory = this.itemFactory;
			if (this.eventHandler && typeof(this.eventHandler) == "function")
			{
				Function.addEventListener(link, "click", this.eventHandler, true);
			}
			else (this.eventHandler && typeof(this.eventHandler) == "object")
			{
				for (var event in this.eventHandler)
				{
					Function.addEventListener(link, event, this.eventHandler[event], true);
				}
			}
		}
		
		var inputs = div.getElementsByTagName("INPUT");
		
		for (var i = 0; i < inputs.length; i++)
		{
			var input = inputs[i];
			input.item = item;
			input.itemFactory = this.itemFactory;
			if (this.eventHandler)
			{
				Function.addEventListener(input, "change", this.eventHandler, false);
			}
		}
		
		item.div = div;
		div.item = item;
		
		return div;
	}
}

/*
* This class create the items and the handler for each one of those items
*/
function ItemFactory()
{
	this.createItems = function() {}
	this.createItemHandler = function(item) {}
}

/*
* Always create and handles the items in the same way
*/
function DefaultItemFactory(items, itemHandler)
{
	this.items = items;
	this.itemHandler = itemHandler;
	
	this.createItems = function()
	{		
		return this.items;
	}
	
	this.createItemHandler = function(item)
	{
		return this.itemHandler;
	}
}

function PropertyItemFactory(propertyName, itemHandler)
{
	this.propertyName = propertyName;
	this.itemHandler = itemHandler;
	
	this.createItems = function(parent)
	{
		assert(parent[this.propertyName], "Property " + this.propertyName + " is not defined.");
		var returnValue = parent[this.propertyName];
		return returnValue;
	}
	
	this.createItemHandler = function()
	{
		return this.itemHandler;
	}
}

function MethodCallerItemFactory(methodName, itemHandler)
{
	this.methodName = methodName;
	this.itemHandler = itemHandler;
	
	this.createItems = function(parent)
	{
		assert(parent[methodName], "Method " + methodName + " is not defined.");
		var returnValue = parent[methodName].call(parent);
		return returnValue;
	}
	
	this.createItemHandler = function()
	{
		return this.itemHandler;
	}
}

function TwoLevelItemFactory(rootItemFactory, leafItemFactory)
{
	this.rootItemFactory = rootItemFactory;
	this.leafItemFactory = leafItemFactory;
	
	this.createItems = function()
	{
		return this.rootItemFactory.createItems();
	}
	
	this.createItemHandler = function(item)
	{
		return new ChildrenItemHandler(this.rootItemFactory, this.leafItemFactory);
	}	
}

function ChildrenItemHandler(rootItemFactory, childrenItemFactory)
{
	this.rootItemFactory = rootItemFactory;
	this.childrenItemFactory = childrenItemFactory;

	this.renderItem = function(item)
	{ 		
		var rootNode = this.rootItemFactory.createItemHandler(item).renderItem(item);		
		var container = document.createElement("div");		
		var childrenContainer = document.createElement("div");
		item.isOpen = false;
		childrenContainer.style.display = 'none';
		var children = this.childrenItemFactory.createItems(item);		
		var links = rootNode.getElementsByTagName("A");
				
		for (var i = 0; i < links.length; i++)
		{
			var link = links[i];
			if (link.getAttribute("name") == "openLevel")
			{				
				link.hierarchyItemFactory = this.hierarchyItemFactory;
				Function.addEventListener(link, "click", this.hierarchyEH, false);
			}
		}
		
		for (var i = 0; i < children.length; i++)
		{
			var child = children[i];
			var childNode = this.childrenItemFactory.createItemHandler(child).renderItem(child);
			childrenContainer.appendChild(childNode);
		}

		item.childrenContainer = childrenContainer;
		
		container.appendChild(rootNode);
		container.appendChild(childrenContainer);
		return container;
	}		
	
	this.hierarchyEH = function(e)
	{
		var src = Function.getSourceElement(e);
		while(src && !src.item)
		{
			src = src.parentNode;
		}
		if (src.item.isOpen)
		{
			src.item.childrenContainer.style.display = 'none';
		}
		else
		{
			src.item.childrenContainer.style.display = 'block';
		}
		src.item.isOpen = !src.item.isOpen;		
		return false;
	}
}

/*
* Creates a Menu using the specified Item Factory
*/
function Menu(container, itemFactory)
{
	this.container = container;
	this.itemFactory = itemFactory;
	itemFactory.menu = this;

	this.show = function()
	{
		//var time1 = new Date();
		this.container.innerHTML = "";
		this.container.appendChild(document.createElement("div"));
		var items = this.itemFactory.createItems();
		this.itemFactory.menu = this;
		for (var i = 0; i < items.length; i++)
		{
			var item = items[i];
			var itemHandler = this.itemFactory.createItemHandler(item);
			itemHandler.itemFactory = this.itemFactory;
			var div = itemHandler.renderItem(item);
			this.container.appendChild(div);
		}
		//alert(new Date() - time1);
	}
}

function Stations(data, template, map, custom)
{
	this.data = data;
	this.template = template;
	this.map = map;
	this.custom = custom;
	
	this.createItems = function()
	{
		if (this.custom && this.custom.search)
		{
			return Function.simpleSearch(data.infos, "name", this.custom.search);
		}
		if (this.custom && this.custom.byLine && this.custom.lineTemplate)
		{
			return data.infos;
		}
		else
		{
			return data.infos;
		}
	}
	
	this.createItemHandler = function(item)
	{
		return new DefaultItemHandler(template, this.openStation);
	}
	
	this.openStation = function(e)
	{
		var src = Function.getSourceElement(e);
		var itemFactory = src.itemFactory;
		itemFactory.map.gmap.setCenter(new GLatLng(src.item.x, src.item.y), 15);
	}
}