/*********************************************************************************
Copyright (C) 2007  Ryan Bowman

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

For any questions or comments contact ryan at fiddlerelf dot com
**********************************************************************************/

var explorerControlId = 0;
var DIRECTORY = "directory";
var	FILE = "file";

function WXExplorer()
{

	this.xmlDoc;
	this.uniqueIdName = "id";
	this.htmlRoot;
	this.componentId = explorerControlId++;
	this.lookAndFeel = MODERN;
	this.draggables = new Array();

	this.setHtmlRoot = FEsetHtmlRoot;
	this.setHtmlTreeRoot = FEsetHtmlTreeRoot;
	this.setHtmlListRoot = FEsetHtmlListRoot;
	this.setXmlDocument = FEsetXmlDocument;
	this.getTreeViewId = FEgetTreeViewId;
	this.getListViewId = FEgetListViewId;
	this.showExplorer = FEshowExplorer;
	this.treeNodeClicked = FEtreeNodeClicked;
	this.createUniqueIds = FEcreateUniqueIds;
	this.setUniqueId = FEsetUniqueId;
	this.nodeHasChildElements = FEnodeHasChildElements;
	this.listNodeDoubleClickedExt = FElistNodeDoubleClickedExt;
	this.listNodeDoubleClicked = FElistNodeDoubleClicked;
	this.createDocumentNode = FEcreateDocumentNode;
	this.createTreeViewNode = FEcreateTreeViewNode;
	this.createListViewNode = FEcreateListViewNode;
	this.createToolTipNode = FEcreateToolTipNode;
	this.showToolTip = FEshowToolTip;
	this.hideToolTip = FEhideToolTip;
	this.setToolTipInfo = FEsetToolTipInfo;
	this.getComponentId = FEgetComponentId;
	this.createAddressBarNode = FEcreateAddressBarNode;
	this.createViewWrapperNode = FEcreateViewWrapperNode;
	this.createViewWrapper2Node = FEcreateViewWrapper2Node;
	this.containerResize = FEcontainerResize;
	this.executeSearch = FEexecuteSearch;
	this.moveUpOneNode = FEmoveUpOneNode;
	this.setLookAndFeel = FEsetLookAndFeel;
	this.getToolTipClass = FEgetToolTipClass;
	this.addressBackClicked = FEaddressBackClicked;
	this.addressForwardClicked = FEaddressForwardClicked;
	this.createViewSliderNode = FEcreateViewSliderNode;
	this.registerDraggable = FEregisterDraggable;
	this.mouseDown = FEmouseDown;
	this.mouseUp = FEmouseUp;
	this.mouseMove = FEmouseMove;
	this.resizeForSeperator = FEresizeForSeperator;


	//extend treeview a little
	this.treeView = new WXTreeView();
	this.treeView.setTreeViewId(this.componentId);
	var treeViewNode = this.createTreeViewNode();
	this.treeView.setHtmlTreeRoot(treeViewNode);
	this.treeView.openTreeNodeExt = FEopenTreeNodeExt;
	this.treeView.addToHistoryExt = FEaddToHistoryExt;
	this.treeView.explorer = this;


	//extend listview a little
	this.listView = new WXListView();
	this.listView.setListViewId(this.componentId);
	var listViewNode = this.createListViewNode();
	this.listView.setHtmlListRoot(listViewNode);
	this.listView.listNodeDoubleClickedExt = FElistNodeDoubleClickedExt;
	this.listView.explorer = this;

	//
	this.addressBar = new WXAddressBar();
	this.addressBar.setComponentId(this.componentId);
	var addressBarNode = this.createAddressBarNode();
	this.addressBar.setHtmlRoot(addressBarNode);
	this.addressBar.explorer = this;

	//create the tooltip node
	this.toolTip = new WXToolTip();
	var toolTipNode = this.createToolTipNode();
	this.toolTip.setHtmlRoot(toolTipNode);

	this.viewWrapper = this.createViewWrapperNode();
	this.viewWrapper2 = this.createViewWrapper2Node();
	this.viewSlider = this.createViewSliderNode();

	this.viewSlider = this.createViewSliderNode()
	this.viewSliderDrag = new WXDraggable(this.viewSlider);
	this.viewSliderDrag.isDragging = FEviewContainerSeperatorDragging;
	this.viewSliderDrag.explorer = this;
	this.registerDraggable(this.viewSliderDrag);

	this.searchService = new WXSearch();
	this.searchService.explorer = this;

	this.history = new WXHistory();
	this.treeView.history = this.history;
	this.addressBar.history = this.history;

	var isIe = document.all ? true : false;
	if (!isIe)
	{
		document.captureEvents(Event.MOUSEMOVE | Event.MOUSEDOWN | Event.MOUSEUP);
	}
	document.onmousemove = mouseMove;
	document.onmousedown = mouseDown;
	document.onmouseup = mouseUp;


}

function FEregisterDraggable(draggable)
{
	this.draggables.push(draggable);
}

function FEsetLookAndFeel(lookAndFeel)
{
	this.lookAndFeel = lookAndFeel;
	this.addressBar.setLookAndFeel(lookAndFeel);
	this.treeView.setLookAndFeel(lookAndFeel);
	this.listView.setLookAndFeel(lookAndFeel);
}

function FEgetComponentId()
{
	return this.componentId;
}

function FEcreateDocumentNode(nodeId)
{
	var divEl = document.createElement("div");
	divEl.setAttribute("id", nodeId);
	return divEl;
}

function FEcreateTreeViewNode(nodeId)
{
	var nodeElement = this.createDocumentNode("treeview");
	return nodeElement;
}

function FEcreateListViewNode(nodeId)
{
	var nodeElement = this.createDocumentNode("listview");
	return nodeElement;
}

function FEcreateToolTipNode(nodeId)
{
	var nodeElement = this.createDocumentNode(this.componentId + "_tooltip");
	nodeElement.className = this.getToolTipClass();
	return nodeElement;
}

function FEgetToolTipClass()
{
	if (this.lookAndFeel == MODERN)
		return "tooltipmodern";
	else
		return "tooltipoldschool";
}

function FEcreateViewWrapperNode(nodeId)
{
	var nodeElement = this.createDocumentNode(this.componentId + "_viewwrapper");
	nodeElement.className = "viewwrapper";
	return nodeElement;
}

function FEcreateViewWrapper2Node(nodeId)
{
	var nodeElement = this.createDocumentNode(this.componentId + "_viewwrapper2");
	nodeElement.className = "viewwrapper2";
	return nodeElement;
}

function FEcreateAddressBarNode(nodeId)
{
	var nodeElement = this.createDocumentNode(this.componentId + "_addressbar");
	nodeElement.className = "addressbar";
	return nodeElement;
}

function FEcreateViewSliderNode(nodeId)
{
	var nodeElement = this.createDocumentNode(this.componentId + "_viewslider");
	nodeElement.className = "viewslider";
	return nodeElement;
}

function FEcreateUniqueIds(xmlEl, idName)
{
	var xmlChildren = xmlEl.childNodes;

	for (var i = 0; i < xmlChildren.length; i++)
	{
		if (xmlChildren[i].nodeType == 1)
		{
			this.setUniqueId(xmlChildren[i], idName);
			if (this.nodeHasChildElements(xmlChildren[i]))	
				this.createUniqueIds(xmlChildren[i], idName);
		}
	}
}

function FEsetUniqueId(xmlEl, idName)
{
	xmlEl.setAttribute(idName, uniqueId++);
}

function FEsetHtmlRoot(nodeId)
{
	this.htmlRoot = document.getElementById(nodeId);
}

function FEsetHtmlTreeRoot(HtmlEl)
{
	this.treeView.setHtmlTreeRoot(HtmlEl);
}

function FEsetHtmlListRoot(HtmlEl)
{
	this.listView.setHtmlListRoot(HtmlEl);
}

function FEsetXmlDocument(xmlDoc, createUniqueId, uniqueIdName)
{
	xmlDoc.setProperty("SelectionLanguage", "XPath");
	this.xmlDoc = xmlDoc;
	
	this.createUniqueIds(this.xmlDoc, this.uniqueIdName);
	this.treeView.setXmlDocument(this.xmlDoc, createUniqueId, uniqueIdName);
	this.listView.setXmlDocument(this.xmlDoc, uniqueIdName);
	this.searchService.setXmlDocument(this.xmlDoc);
}

function FEgetTreeViewId()
{
	return this.treeView.getTreeViewId();
}

function FEgetListViewId()
{
	return this.listView.getListViewId();
}

function FEshowExplorer()
{
	this.htmlRoot.appendChild(this.addressBar.htmlRoot);
	this.addressBar.showAddressBar();
	this.htmlRoot.appendChild(this.viewWrapper);
	this.viewWrapper.appendChild(this.viewWrapper2);
	this.viewWrapper2.appendChild(this.treeView.htmlRoot);
	this.viewWrapper2.appendChild(this.viewSlider);
	this.viewWrapper2.appendChild(this.listView.htmlRoot);
	this.viewWrapper2.appendChild(this.toolTip.htmlRoot);
	this.treeView.createTree();
	// remember to fix this up above! change all this crap actually!!
	this.toolTip.htmlRoot.className = this.getToolTipClass();

}

function FEnodeHasChildElements(node)
{
	var children = node.childNodes;
	for (var i = 0; i < children.length; i++)
	{
		if (children[i].nodeType == 1)
			return true;
	}
	return false;
}

function FEtreeNodeClicked(nodeId, clickedType)
{
	this.toolTip.hideToolTip();
	var xmlNode = this.treeView.getXmlElementById(nodeId);
	this.treeView.treeNodeClicked(xmlNode, clickedType);
}

function FElistNodeDoubleClicked(nodeId, clickedType)
{
	this.toolTip.hideToolTip();
	this.listView.listNodeDoubleClicked(nodeId, clickedType);
}

function FElistNodeDoubleClickedExt(nodeId, clickedType)
{
	var xmlNode = this.explorer.treeView.getXmlElementById(nodeId);
	this.explorer.treeView.treeNodeClicked(xmlNode, "treenodeicon");
}

function FEaddToHistoryExt(nodeId)
{
	this.explorer.addressBar.historyModified();
}

function FEopenTreeNodeExt(xmlNode)
{
	this.explorer.listView.populateListFromNode(xmlNode);
	this.explorer.addressBar.setAddress(this.getNodePath(xmlNode));
	this.explorer.addressBar.enableUp(xmlNode != this.xmlDoc.documentElement);
}

function FEshowToolTip(e)
{
	this.toolTip.showToolTip(e);
}

function FEhideToolTip()
{
	this.toolTip.hideToolTip();
}

function FEsetToolTipInfo(nodeId, componentId, componentName)
{
	var component;
	switch (componentName)
	{
		case "listview":
		{
			component = this.listView;
		}
		break;
		case "treeview":
		{
			component = this.treeView;
		}
		break;
	}
	
	var fileInfo = component.getToolTipInfo(nodeId);		
	this.toolTip.setToolTipInfo(fileInfo);
}

function FEexecuteSearch()
{
	var nodes;
	var searchString = this.addressBar.searchForm.searchField.value;
	if (searchString && searchString != '')
	{
		nodes = this.searchService.search(searchString);
		this.listView.clearList();
		if (nodes.length > 0)
		{
			for (var i = 0; i < nodes.length; i++)
			{
				this.listView.htmlRoot.appendChild(this.listView.createListNode(nodes[i]));
			}
		}
		else
		{
			var spanEl = document.createElement("span");
			spanEl.innerHTML = "<em>Your search did not return any results.</em>";
			this.listView.htmlRoot.appendChild(spanEl);
		}
	}
}

function FEmoveUpOneNode(e)
{
	this.treeView.moveUpOneNode();
}

function FEaddressBackClicked(e)
{
	var nodeId = this.history.previous();
	this.addressBar.historyModified();
	this.treeView.gotoNode(nodeId);
}

function FEaddressForwardClicked(e)
{
	var nodeId = this.history.next();
	this.addressBar.historyModified();
	this.treeView.gotoNode(nodeId);
}

function FEmouseDown(nodeId)
{
	for (var i = 0; i < this.draggables.length; i++)
	{
		if (this.draggables[i].htmlRoot.getAttribute("id") == nodeId)
		{
			this.draggables[i].mouseDown();
			return;
		}
	}
}

function FEmouseUp()
{
	for (var i = 0; i < this.draggables.length; i++)
	{
		this.draggables[i].mouseUp();
	}
}

function FEmouseMove(e)
{
	for (var i = 0; i < this.draggables.length; i++)
	{
		this.draggables[i].mouseMove(e);
	}
}

function FEviewContainerSeperatorDragging(xpos, ypos)
{
	var containerWidth = this.explorer.htmlRoot.offsetWidth;
	var containerLeft = this.explorer.htmlRoot.style.left;
	var containerRight = containerWidth + containerLeft
	var leftBound = containerLeft + 200;
	var rightBound = containerRight - 300;
	
	if ((xpos > leftBound) && (xpos < rightBound))
	{
		this.htmlRoot.style.left = xpos + "px";
		var treeViewPercentage = 100 * ((xpos - containerLeft - 10) / containerWidth);
		var listViewPercentage = 100 * ((containerRight - xpos + this.htmlRoot.offsetWidth) / containerWidth);
		this.explorer.treeView.htmlRoot.style.width = treeViewPercentage + "%";
		this.explorer.listView.htmlRoot.style.width = listViewPercentage + "%";
	}
}

function FEresizeForSeperator()
{
	var containerWidth = this.htmlRoot.offsetWidth;
	var containerLeft = this.htmlRoot.style.left;
	var containerRight = containerWidth + containerLeft

	var xpos = normGetPixels(this.viewSlider.style.left)
	var treeViewPercentage = 100 * ((xpos - containerLeft - 10) / containerWidth);
	var listViewPercentage = 100 * ((containerRight - xpos + this.viewSlider.offsetWidth) / containerWidth);
	this.treeView.htmlRoot.style.width = treeViewPercentage + "%";
	this.listView.htmlRoot.style.width = listViewPercentage + "%";

}

function FEcontainerResize(e)
{
	var treeViewNode = this.treeView.htmlRoot;
	var listViewNode = this.listView.htmlRoot;
	var addressBarNode = this.addressBar.htmlRoot;
	var addressFormNode = this.addressBar.addressForm.htmlRoot;
	var searchFormNode = this.addressBar.searchForm.htmlRoot;
	var addressFieldNode = this.addressBar.addressForm.addressField;
	var containerWidth = this.htmlRoot.offsetWidth;
	var containerLeft = this.htmlRoot.style.left;

	var addressFormWidth = addressFormNode.offsetWidth;
	var addressFieldWidth = addressFieldNode.offsetWidth;
	var addressButtonsWidth = 100; // for shits sake
	
	var searchFormWidth = searchFormNode.offsetWidth;
	var targetAddressFormWidth = containerWidth - searchFormWidth;
	
	var searchFormPercentage = Math.round((searchFormWidth )/containerWidth * 100)
	var newAddressFormPercentage = 95 - searchFormPercentage;
	if (newAddressFormPercentage > 0)
	{
		addressFormNode.style.width = newAddressFormPercentage + "%";
	}
	
	var newAddressFieldWidth = (100 - Math.round(addressButtonsWidth/targetAddressFormWidth * 100));
	if (newAddressFieldWidth > 0)
		addressFieldNode.style.width = newAddressFieldWidth + "%";
		
	if (containerLeft == "")
		containerLeft = 0;
	
	var viewHeight = (.95 * (getHeight() - searchFormNode.offsetHeight))
	if (treeViewNode)
		treeViewNode.style.height = viewHeight + "px";
	
	if (listViewNode)
		listViewNode.style.height = viewHeight + "px";
		
	if (this.viewSlider)
	{
		this.viewSlider.style.height = viewHeight + "px";
		this.viewSlider.style.left = this.htmlRoot.offsetWidth - listViewNode.offsetWidth + "px";
		this.resizeForSeperator();	
	}
	
}
