<%
// SET THIS VARIABLE TO TRUE TO USE PRIMITIVE SERIALIZATION (HIGHLY EXPERIMENTAL!!!)
boolean bUseSerialize = false;

// Global counter of tree nodes
int _id = 0;
// Tree-node class
xpDirectory(int iID, String sLabel, String sURL) {
	int ID			= iID;		// Node ID
	String Label		= sLabel;	// Label (What is shown in the tree)
	String URL		= sURL;		// URL to this folder
	Vector Children		= new Vector(); // Array containing child nodes
	int Level		= 0;		// Level of indentation for the current node
	Object Parent		= null;		// Reference to parent node

	// Method that adds a node as a child to a parent
	addChild(lchild) {
		lchild.Level	= this.Level + 1;
		lchild.Parent	= this;
		this.Children.addElement(lchild);
	}
	
	// Method that serializes a node (and all sub-nodes) to a file
	serialize(BufferedWriter fOut) {
		if (this.Parent == null)
			fOut.write("-1");
		else
			fOut.write(this.Parent.ID.toString());
		fOut.newLine();
		fOut.write(this.Label);
		fOut.newLine();
		fOut.write(this.URL);
		fOut.newLine();
		for (Object node : this.Children)
			node.serialize(fOut);
	}
	
	return this;
}
// Function that's called recursively to add all subfolders to directory structure
addChildren(parent) {
	File directory = new File(parent.URL);
	File[] localFiles = engine.listFiles(directory, true, directory);
	for (File f : localFiles) {
		if (f.isDirectory()) {
			child = xpDirectory(_id++, f.getName(), f.getPath());
			parent.addChild(child);
			addChildren(child);
		}
	}
}

// Root of directory structure
Object root = null;

if (bUseSerialize) {
	try {
		Object node;
		Object previousNode = null;
		// Open tree.dat if it exists
		BufferedReader fIn = new BufferedReader(new FileReader(engine.getOutputDirectory() + "/tree.dat"));
		String str;
		int fID;
		String fLabel;
		String fURL;
		int Step = 0;
		
		// Read all lines from tree.dat
		while ((str = fIn.readLine()) != null) {
			Step++;
			if (Step == 1)
				fID = Integer.parseInt(str);
			if (Step == 2)
				fLabel = str;
			if (Step == 3) {
				Step = 0;
				fURL = str;
				
				if (fID == -1) {
					// Create root node
					root = xpDirectory(_id++, fLabel, fURL);
					previousNode = root;
				} else {
					// Create child node
					node = xpDirectory(_id++, fLabel, fURL);
					while (previousNode.ID != fID)
						previousNode = previousNode.Parent;
					previousNode.addChild(node);
					previousNode = node;
				}
			}
		}
		// Close stream
		fIn.close();
	} catch (IOException e) { 
	}
}

// We haven't used the serialization option or it is the first tree we're rendering
if (root == null) {
	File rootDir = new File(engine.getDirectory());
	root = xpDirectory(_id++, rootDir.getName(), rootDir.getPath());
	addChildren(root);
	
	// If we're using the serialization option - create the tree.dat file and store the data
	if (bUseSerialize) {
		try {
			BufferedWriter fOut = new BufferedWriter(new FileWriter(engine.getOutputDirectory() + "/tree.dat"));
			root.serialize(fOut);
			fOut.close();
		} catch (IOException e) {
		}
	}
}


int step  = 0;
int lLevel = 0;
String sPrefix = "";
for (int lLoop = 0; lLoop < level; lLoop++) sPrefix += "../";

// This method creates HTML for one node in the tree
printNode(item, hasSiblings) {
	step++;
	
	out.print("<div style=\"left: " + ((lLevel == 0)?("0"):("17")) + "px;\" id=\"folder" + step + "\" class=\"folderHas" + ((hasSiblings)?(""):("No")) + "Siblings\"><nobr><a href=\"#\" onclick=\"toggleNode(" + step + "); return false;\"><img name=\"img" + step + "\" src=\"" + resPath + "/Tree" + ((item.Children.size() > 0)?("Plus"):("Dot")) + ".gif\" border=\"0\" alt=\"\" width=\"19\" height=\"17\"/></a><img src=\"" + resPath + "/IconFolder.gif\" border=\"0\" alt=\"\" width=\"16\" height=\"16\" align=\"top\"/>&nbsp;<span class=\"top\"><a class=\"blank\" href=\""); 
	
	String sPath = "";
	// If we're on a slide page - add a level of ..
	if (currentPage != void)
		sPath += "../";
	sPath += sPrefix;
	sPath += item.Label;
	sPath += "/" + engine.getIndexPageName() + engine.getPageExtension();
		
	out.print(sPath + "\">" + item.Label + "</a></span></nobr>\n");
	out.print("<div id=\"folder" + step + "c\" style=\"display: none;\">\n");
	
	lLevel++;
	String sPreviousPrefix = sPrefix;

	if (item.Level == 0) {
		sPrefix = sPreviousPrefix + root.Label + "/" + item.Label + "/";
	} else {
		sPrefix = sPreviousPrefix + item.Label + "/";
	}

	for (int i = 0; i < item.Children.size(); i++)
		printNode(item.Children.get(i), (i < (item.Children.size() - 1)));
		
	sPrefix = sPreviousPrefix;
	lLevel--;
	
	out.print("</div>\n");
	out.print("</div>\n");
}

%>
<div id="divFolders">
<a href="#" onclick="saveCookie('ShowFolders', 'false'); xLeft('divFolders',-1000); return false;" id="aCloseFolder"></a>
<div id="divFolderHeader">$text.folders</div>
<div id="divTree">

<div id="folderTop"><img src="$resPath/IconFolder.gif" border="0" alt="" width="16" height="16" align="absbottom"/><nobr>&nbsp;<a class="blank" href="<%for (int lLoop = 0; lLoop < level; lLoop++) out.print("../"); if (currentPage != void) out.print("../");%><%=engine.getIndexPageName()%><%=engine.getPageExtension()%>"><%=root.Label%></a></nobr>
<%
	for (int i = 0; i < root.Children.size(); i++)
		printNode(root.Children.get(i), (i < (root.Children.size() - 1)));
%>
</div>

</div>
</div>
<script language="javascript">
try {
	if (readCookie('ShowFolders') == 'true')
	    xLeft('divFolders', 0);
} catch (ex) {}
</script>