/// <reference path="jquery/jquery-vsdoc.js" />

var latestXML = "";
//var updateFunctions = new Array();
var updateFunctionInfo = {};

// Object definitions
function ViewEntry (node) {
	this.compID = node.attr("compid");
	this.name = node.attr("name");
	this.template = node.attr("template");
	this.toString = function() {
		return this.name;
	};
}

var systemViews = {};
var nodeViews = {};
var catalogViews = {};
var moduleViews = {};
var customViews = new Array();

var nodeViewNames = new Array();
var catalogViewNames = new Array();
var moduleViewNames = new Array();

function processTemplateXML(xmldoc) {
	if (!xmldoc) return;
	$xml = $(xmldoc);
	var m, n = 0;
	var systemviewnames = new Array();
	var systembuttonnames = new Array();
	var name;
	var template;
	$xml.find("views systemviews systemview").each(function () {
		systemviewnames.push($(this).attr("name"));
	});

	$xml.find("views systemviews systemview").each(function () {
		systemViews[$(this).attr("name")] = new ViewEntry($(this));
	});

	// Remove old buttons no longer in the list
	removeOldButtons(systemviewnames, "SystemLine", systembuttonnames, "Header");
	// Add new buttons and views to system
	addNewButtons(systemViews, "System", systembuttonnames, "Header");
	
	$("#SystemView").slideUp('fast').data("CompName", "System").data("CompType", "System")

	$xml.find("views nodeviews nodeview").each(function () {
		nodeViews[$(this).attr("name")] = new ViewEntry($(this));
	});
	
	$xml.find("views catalogviews catalogview").each(function () {
		catalogViews[$(this).attr("name")] = new ViewEntry($(this));
	});

	$xml.find("views moduleviews moduleview").each(function () {
		moduleViews[$(this).attr("name")] = new ViewEntry($(this));
	});
}

function showOnline() {
	$('#PageStatus').html("");
}

function showOffline() {
	$('#PageStatus').html("<font color=red><b>Offline</b></font>");
}

function checkPsycloneConnection() {
	var xmldoc = loadURL("/time.xml");
	if (typeof xmldoc != "undefined") {
		var $xml = $(xmldoc);
		var sysID = $xml.attr("id");
		if (SystemID.length && (sysID != SystemID)) {
			flashStatus("Psyclone was restarted - reloading...", 2000);
			setTimeout(function(){location.reload(true);},2500);
		}
		SystemID = sysID;
		SystemTime = new PsyTime($xml.attr("time"));
		SystemUptime = $xml.attr("uptime");
		$('#PageClock').html(SystemTime.toTimeString());
		$('#PageUptime').html(PrintTimeDiffApprox(SystemUptime));
		showOnline();
	}
	else {
		showOffline();
	}
}

function processMainXML(xmldoc) {

	if (!xmldoc) {
		showOffline();
		return;
	}
	showOnline();
	$xml = $(xmldoc);
	var system = $xml.find('system:first');

	var sysID = system.attr("id");
	if (SystemID.length && (sysID != SystemID)) {
		flashStatus("Psyclone was restarted - reloading...", 2000);
		setTimeout(function(){location.reload(true);},2500);
	}

	processSystemXMLNode(system);

	$('#PageClock').html(SystemTime.toTimeString());
	$('#PageUptime').html(PrintTimeDiffApprox(SystemUptime));

	SetActivityImage($('#PageSystemCPU1'), SystemUsage1);
	SetActivityImage($('#PageSystemCPU2'), SystemUsage2);
	SetActivityImage($('#PageSystemCPU3'), SystemUsage3);
	
	nodeViewNames.length = 0;
	for (var node in nodeMap)
		nodeViewNames.push(nodeMap[node].name);
	catalogViewNames = GetCatalogNames();
	moduleViewNames = GetModuleNames();

	$xml.find("customviews customview").each(function () {
		customViews.push(new ViewEntry($(this)));
	});
	
	// Fill in the system info text dropdown
	fillInfoDropdown($xml.find("systeminfo text"), "SystemLineText", "SystemLineDropDown", "SystemLineDropDownLine");

	// Add nodes
	for (var n=1; n<=20; n++)
		$('#PageNodeCPU' + n).attr("src", "images/active_none.gif");
	for (var nodeID in nodeMap) {
		var node = nodeMap[nodeID];
		fillEntryInfo(node, "Node");
		SetActivityImage($('#PageNodeCPU' + nodeID + '-1'), node.perfStats.computercpuusage1);
		SetActivityImage($('#PageNodeCPU' + nodeID + '-2'), node.perfStats.computercpuusage2);
		SetActivityImage($('#PageNodeCPU' + nodeID + '-3'), node.perfStats.computercpuusage3);
	}

	// Add catalogs
	for (var compID in componentMap) {
		var component = componentMap[compID];
		if ( (component.type == 1) || (component.type == 2) ) {
			fillEntryInfo(component, "Catalog");
		}
	}

	// Add modules
	for (var compID in componentMap) {
		var component = componentMap[compID];
		if ( (component.type == 6) || (component.type == 7) ) {
			fillEntryInfo(component, "Module");
		}
	}

	// $systeminfo = $xml.find('systeminfo:first');
	// $systeminfo.find("resources").each(function () {
	// });
	
	// $(this).find("resources").each(function () {
	   // console.log("System memory: " + $(this).attr("memory"));
	   // console.log("System cpu: " + $(this).attr("cpu"));
	// });

	updateSectionViews();
	runUpdateFunctions();
}

function fillEntryInfo(entry, entryType) {
	//   <node id="1" name="Odin" address="192.168.0.10" port="10000" group="Indoor">
	if (!($entryView = $("#" + entryType + "sView").get(0)))
		return;

	var viewnames;
	var views;
	var buttonnames = new Array();
	var text;
	var template;
	var activeTriggers;
	var inactiveTriggers;
	if ("Node" == entryType) {
		text = "Address: " + entry.address + ":" + entry.port + ", " +
			Object.keys(GetNodeSpaces(entry.id)).length + " Spaces, " +
			Object.keys(GetNodeCatalogs(entry.id)).length + " Catalogs, " +
			Object.keys(GetNodeModules(entry.id)).length + " Modules";
		views = nodeViews;
		// viewnames = nodeViewNames;
	}
	else if ("Catalog" == entryType) {
		//text = "Params: " + entry.paramcount + " Data: " + entry.datacount;
		text = "Msg in: " + entry.stats.msgincount + "<sup>(" + Sizify(entry.stats.msginbytes) + ")</sup> out: " + entry.stats.msgoutcount + "<sup>("+ Sizify(entry.stats.msgoutbytes) +")</sup> - ";

		activeTriggers = GetTriggers(entry.id, true);
		inactiveTriggers = GetTriggers(entry.id, false);
		if (activeTriggers.length)
			text += "<span class='ActiveTrigger'>"+activeTriggers.length+" active trigger(s)</span> <span class='InactiveTrigger'>("+inactiveTriggers.length+" inactive)</span>"
		else if (inactiveTriggers.length)
			text += "<span class='InactiveTrigger'>("+inactiveTriggers.length+" inactive trigger(s))</span>"
		else
			text += "<span class='InactiveTrigger'>(no triggers registered)</span>"
		views = $.extend(true, [], catalogViews);
		// add custom views
		jQuery.each( customViews, function( i, val ) {
			if (val.compID == entry.id)
				views[val.name] = val;
		});
		// viewnames = catalogViewNames;
	}
	else if ("Module" == entryType) {
		// text = "Params: " + entry.paramcount + " Data: " + entry.datacount;
		text = "Msg in: " + entry.stats.msgincount + "<sup>(" + Sizify(entry.stats.msginbytes) + ")</sup> out: " + entry.stats.msgoutcount + "<sup>("+ Sizify(entry.stats.msgoutbytes) +")</sup> - ";
		
		activeTriggers = GetTriggers(entry.id, true);
		inactiveTriggers = GetTriggers(entry.id, false);
		if (activeTriggers.length)
			text += "<span class='ActiveTrigger'>"+activeTriggers.length+" active trigger(s)</span> <span class='InactiveTrigger'>("+inactiveTriggers.length+" inactive)</span>"
		else if (inactiveTriggers.length)
			text += "<span class='InactiveTrigger'>("+inactiveTriggers.length+" inactive trigger(s))</span>"
		else
			text += "<span class='InactiveTrigger'>(no triggers registered)</span>"
		views = $.extend(true, [], moduleViews);
		// add custom views
		jQuery.each( customViews, function( i, val ) {
			if (val.compID == entry.id)
				views[val.name] = val;
		});
		// viewnames = moduleViewNames;
	}

	var tag = entryType + "_" + entry.id;
	// Check if node is already there

	if (!($entry = $("#" + tag)).get(0)) {
		// If not, load new template and add it to html
		$entry = $("<div id='" + tag + "'></div>").appendTo($entryView).html(loadURL('elements/' + entryType.toLowerCase() + 'entry.html'));
		$entry.find("#" + entryType + "LineHeadline").attr('id', tag + 'LineHeadline');
		$entry.find("#" + entryType + "LineText").attr('id', tag + 'LineText');
		$entry.find("#" + entryType + "View").attr('id', tag + 'View').data("CompName", entry.name).data("CompType", entryType);
		$entry.find("#" + entryType + "LineSelect").attr('id', tag + 'LineSelect').data("Section", tag).data("Command", "Select").data("Selected", "").data("View", tag);
		$entry.find("#" + entryType + "LineUpdate").attr('id', tag + 'LineUpdate').data("Section", tag).data("Command", "Update").data("Updating", "yes").data("View", tag);
		$entry.find("#" + entryType + "LineCollapse").attr('id', tag + 'LineCollapse').data("Section", tag).data("Target", tag+'View').data("Command", "Expand").html("<img src=\"images/expand.png\" width=10 height=10>");
		$entry.find("#" + entryType + "LineGroups").attr('id', tag + 'LineGroups').data("Section", tag);
		$entry.find("#" + entryType + "LineActivity").attr('id', tag + 'LineActivity');
		$entry.find("#" + entryType + "Line0").attr('id', tag + 'Line0');
		$entry.find("#" + entryType + "Line1").attr('id', tag + 'Line1');
		$entry.find("#" + entryType + "Line2").attr('id', tag + 'Line2');
		$entry.find("#" + entryType + "Line3").attr('id', tag + 'Line3');
		$entry.find("#" + entryType + "Line4").attr('id', tag + 'Line4');
		$entry.find("#" + entryType + "Line5").attr('id', tag + 'Line5');
		$entry.find("#" + entryType + "Line6").attr('id', tag + 'Line6');
		$entry.find("#" + entryType + "Line7").attr('id', tag + 'Line7');
		$entry.find("#" + entryType + "Line8").attr('id', tag + 'Line8');
		$entry.find("#" + entryType + "LineDropDown").attr('id', tag + 'LineDropDown');
		$entry.find("#" + entryType + "LineDropDownContent").attr('id', tag + 'LineDropDownContent');
		$entry.find("#" + entryType + "View").attr('id', tag + 'View');
		$("#" + tag + "View").slideUp('fast');
		$entry.on('click', 'td', function (event) { processHeaderLineClick($(this)); });
	}
	if ("Node" == entryType)
		setActivity(tag, entry.perfStats.localsystemcpuusage1);
	else
		setActivity(tag, entry.perfStats.percentofsystemcpu1);
	$("#" + tag + 'LineHeadline').html(entryType + " " + entry.id + ": " + entry.name);
	$("#" + tag + 'LineText').html(text);
	
	// Remove old buttons no longer in the list
	removeOldButtons(Object.keys(views), tag + "Line", buttonnames, "Entry");
	// Add new buttons and views to node
	addNewButtons(views, tag, buttonnames, "Entry");
	// Fill in template html for the node

}

function processHeaderLineClick(comp) {
	if (!comp)
		return;
	var id = comp.attr("id");
	if (!id || ("" == id))
		return;
	var cmd = comp.data("Command");
	var target = comp.data("Target");
	var section = comp.data("Section");

	if (!cmd || ("" == cmd)) {
		if (!section && ("" == (section = getSectionNameFromID(id))))
			return;
		comp.data("Section", section);
		comp.data("Target", target = section+"View");
		//console.log("comp.html: " + comp.html());
		if (comp.html().indexOf("collapse.png"))
			comp.data("Command", cmd = "Collapse");
		else if ("Selected" == comp.text())
			comp.data("Command", cmd = "ShowOnlySelected");
		else if (comp.text().indexOf("Groups") > 0)
			comp.data("Command", cmd = "LoadTemplate");
	}

	$collapseButton = $("#" + section + "LineCollapse");
	$target = $("#" + target + "");
	console.log("Click: " + comp.text() + " cmd: " + cmd + " target: " + target);

	if ("Collapse" == cmd) {
		$target.slideUp('fast');
		comp.children('img')[0].src = "images/expand.png";
		// comp.html("<img src=\"images/expand.png\" width=12 height=12>");
		comp.data("Command", "Expand");
		delete updateFunctionInfo[$target.data("CompType")+"_"+$target.data("CompName")];
		return;
	}
	else if ("Expand" == cmd) {
		$target.slideDown('fast');
		comp.children('img')[0].src = "images/collapse.png";
		comp.data("Command", "Collapse");
		return;
	}
	else if ("LoadTemplate" == cmd) {
		$target.slideDown('fast');
		$collapseButton.children('img')[0].src = "images/collapse.png";
		// $collapseButton.html("<img src=\"images/collapse.png\" width=10 height=10>");
		$collapseButton.data("Command", "Collapse");
		$collapseButton.data("Target", section + "View");
		if ((template = comp.data("Template")) && (template != $target.data("Template"))) {
			$target.data("Template", template);
			$target.data("TemplateName", comp.data("TemplateName"));
			loadTemplate(template, $target, $target.data("TemplateName"), $target.data("CompName"), $target.data("CompType"), true);
			// $target.load(template);
		}
		runUpdateFunctions();
	}
	else if ("DropDownMenu" == cmd) {
		if ("none" == $target.css("display"))
			$target.slideDown('fast');
		else
			$target.slideUp('fast');
	}
	else if ("DropDownMenuSelect" == cmd) {
		if ($dropdown = $("#" + comp.data("DropDown") + "")) {
			$dropdown.slideUp('fast');
			if ($target) {
				$dropdown.data("currentlyselectedname", comp.attr("name"));
				$target.text($dropdown.data(comp.attr("name")));
			}
		}
	}
	else if ("Select" == cmd) {
		if ("yes" != comp.data("Selected")) {
			comp.data("Selected", "yes");
			comp.addClass("EntryLineSelected");
		}
		else {
			comp.data("Selected", "");
			comp.removeClass("EntryLineSelected");
		}
	}
	else if ("Update" == cmd) {
		if ("yes" != comp.data("Updating")) {
			comp.data("Updating", "yes");
			comp.removeClass("EntryLineNotUpdating");
			comp.addClass("EntryLineUpdating");
		}
		else {
			comp.data("Updating", "");
			comp.removeClass("EntryLineUpdating");
			comp.addClass("EntryLineNotUpdating");
		}
	}
	else if ("ShowOnlySelected" == cmd) {
		$target.data("Show", "Selected");
		comp.data("Command", "ShowAll");
		comp.text("All");
	}
	else if ("ShowAll" == cmd) {
		$target.data("Show", "All");
		comp.data("Command", "ShowOnlySelected");
		comp.text("Selected");
	}

	updateSectionViews();
}

function fillInfoDropdown(collection, target, dropdown, itemID) {
    //$xml.find("systeminfo text"), "SystemLineText", "SystemLineDropDown", "SystemLineDropDownLine");
    var html;
    var count = 0;
    if ($text = $("#" + target)) {
        if (($dropdown = $("#" + dropdown)).get(0)) {
            $dropdown.empty();
            $dropdown.append("<table>");
            collection.each(function () {
                $dropdown.append("<tr>");
                html = "<td class='HeaderLineDropDownLine' id='" + itemID + (count++) + "' name='" + $(this).attr("name") + "'>" + $(this).attr("text") + "</td>"
                $entry = $(html).appendTo($dropdown).data("Target", target).data("DropDown", dropdown).data("Command", "DropDownMenuSelect");
                $dropdown.append("</tr>");
                $dropdown.data($(this).attr("name"), $(this).attr("text"));
            });
            $dropdown.append("</table>");
            $text.data("Command", "DropDownMenu");
            $text.data("Target", dropdown);

            $name = $dropdown.data("currentlyselectedname");
            if (!$name || ("" == $name)) {
                $name = collection.first().attr("name");
                $dropdown.data("currentlyselectedname", $name);
            }
            $text.text($dropdown.data($name));
        }
    }
}

function removeOldButtons(newNames, idPrefix, existingButtonNames, typeName) {
    for (n = 0; n < 10; n++) {
        if (($button = $("#" + idPrefix + n)).get(0)) {
            if ("" != (name = $button.text())) {
                if (newNames.indexOf(name) < 0) {
					// console.log("Removing old button: " + name + " - not in list " + newNames.toString());
                    name = "";
                    $button.text("");
                    $button.removeData();
                    $button.removeClass(typeName + "LineButton");
                }
            }
            // Reshuffle leftover buttons down
            if ("" == name) {
                for (m = n; m < 5; m++) {
                    if (($button2 = $("#" + idPrefix + m)).get(0)) {
                        if ("" != (name = $button2.text())) {
							// console.log("Shifting button2: " + name + " to button1: " + $button.text());
                            // shift button2 at m to button1 at n
                            $button.data($button2.data());
                            $button.text($button2.text());
                            $button.addClass(typeName + "LineButton");
                            // clear button2 at m
                            $button2.text("");
                            $button.removeData();
                            $button2.removeClass(typeName + "LineButton");
                            break;
                        }
                    }
                }

            }
            existingButtonNames[n] = name;
        }
    }
}

function addNewButtons(map, section, existingButtonNames, typeName) {
	// console.log("addNewButtons: " + section + " " + typeName);
	for (var ntry in map) {
		var entry = map[ntry];
        if (existingButtonNames.indexOf(entry.name) < 0) {
            // Find first empty button
            if ((n = existingButtonNames.indexOf("")) >= 0) {
                if (($button = $("#" + section + "Line" + n)).get(0)) {
                    $button.text(entry.name);
                    $button.data("Command", "LoadTemplate");
                    $button.data("Section", section);
                    $button.data("Target", section + "View");
                    $button.data("Template", entry.template);
                    $button.data("TemplateName", entry.name);
                    existingButtonNames[n] = entry.name;
                    $button.addClass(typeName + "LineButton");
                }
            }
        }
    };
}

function setActivity(compName, level) {
	SetActivityImage($("#" + compName + 'LineActivity'), level);
}

function loadURL(url) {
    return $.ajax({
        type: "GET",
        url: url,
        cache: false,
        async: false
    }).responseText;
}


function PrintMessageTable(msg) {
	if (typeof msg == 'undefined')
		return;
	
	var ttl;
	if (msg.ttl == 0)
		ttl = "<i>Not stored</i>";
	else {
		var newTime = jQuery.extend(true, {}, msg.time);
		newTime.addUS(msg.ttl);
		var timeRemainUS = msg.getRemainingTTLUS();
		if (timeRemainUS > 1000000) {
			ttl = "<font color=red><nobr><b>YES</b></font> until " + newTime.toString() + "</nobr><br><nobr>(for another " + PrintTimeDiffFull(timeRemainUS) + ")</nobr>";
			if (msg.memid > 0)
				ttl += "<nobr><br>(MemID: <i>"+msg.memid+"</i>)</font>";
			// ttl = "<font color=red><b>LIVE </b><i> ("+timeRemainUS+")</i></font>";
		}
		else {
			if (timeRemainUS > -1000000)
				ttl = "<nobr>Expired " + newTime.toString() + "<nobr><br><nobr>(moments ago)</nobr>";
			else
				ttl = "<nobr>Expired " + newTime.toString() + "<nobr><br><nobr>(" + PrintPsyTimeAgeFull(newTime) + " ago)</nobr>";
		}
	}

	var type;
	if (msg.contextchange.length)
		type = "<font color=black size='-2'>Message Context Change<br></font> <font color=blue size='-1'><b>" + GetContext(msg.contextchange) + "</b></font>"
	else
		type = "<font color=black size='-2'>Message Type<br></font> <font color=green size='-1'><b>" + GetType(msg.type) + "</b></font>"
	
	var userDataRow = 0;
	var userDataRows = "";
	for (var [key, value] of msg.userEntries) {
		if (userDataRow % 2)
			userDataRows += "<tr class='MessageTableLineAlternate'><td>" + key + "</td><td colspan=3 class='MessageTableValue'>" + value.toString() + "</td></tr>";
		else
			userDataRows += "<tr class='MessageTableLine'><td>" + key + "</td><td colspan=3 class='MessageTableValue'>" + value.toString() + "</td></tr>";
		userDataRow++;
	}

	return type +
		"<head><meta charset=\"utf-8\" /><title>PsyProbe Message</title><link rel=\"stylesheet\" type=\"text/css\" href=\"http://localhost:10000/main.css\" /></head><body>" +
		"<table class='MessageTable'>"+
		//"<tr align=center><td>Type</td><td>From</td><td>Size</td><td>Age</td></tr>"+
		"<tr class='MessageTableLineAlternate'><td>Size</td><td colspan=3 class='MessageTableValue'>" + Sizify(msg.size) + "</td></tr>" +
		"<tr class='MessageTableLine'><td>Created</td><td colspan=3 class='MessageTableValue'><nobr>" + msg.time.toString() + "</nobr><br><nobr>(" + PrintPsyTimeAgeFull(msg.time) + " ago)</nobr></td></tr>" +
		"<tr class='MessageTableLineAlternate'><td>Sent</td><td colspan=3 class='MessageTableValue'><nobr>" + (msg.sendtime.isValid() ? msg.sendtime.toString() : "N/A") + "<nobr>" + (msg.sendtime.isValid() ? ("<br><nobr>(" + PrintPsyTimeAgeFull(msg.sendtime) + " ago)</nobr>") : "") + "</td></tr>" +
		"<tr class='MessageTableLine'><td>Stored</td><td colspan=3 class='MessageTableValue'>" + ttl + "</td></tr>" +
		"<tr class='MessageTableLineAlternate'><td>From</td><td colspan=3 class='MessageTableValue'>" + GetComponentName(msg.from) + "</td></tr>" +
		"<tr class='MessageTableLine'><td>To</td><td colspan=3 class='MessageTableValue'>" + GetComponentName(msg.to) + "</td></tr>" +

		"<tr class='MessageTableLineAlternate'><td width=\"25%\">Origin</td><td width=\"25%\" class='MessageTableValue'>" + msg.origin + "</td>" +
		"<td width=\"25%\">Destination</td><td width=\"25%\" class='MessageTableValue'>" + msg.destination + "</td></tr>" +

		"<tr class='MessageTableLine'><td>Priority</td><td class='MessageTableValue'>" + msg.priority + "</td>"+
		"<td>Policy</td><td class='MessageTableValue'>" + msg.policy + "</td></tr>" +

		"<tr class='MessageTableLineAlternate'><td>Tag</td><td class='MessageTableValue'>" + msg.tag + "</td>"+
		"<td>Status</td><td class='MessageTableValue'>" + msg.status + "</td></tr>" +

		"<tr class='MessageTableLine'><td>Reference</td><td class='MessageTableValue'>" + msg.reference + "</td>"+
		"<td><nobr>Serial</nobr></td><td class='MessageTableValue'><nobr>" + msg.serial + "</nobr></td></tr>" +
		"<tr class='MessageTableLineUser'><td colspan=2><nobr>User entries</nobr></td><td colspan=2 class='MessageTableValue'><nobr>" + msg.userdatacount + " (size: " + Sizify(msg.userdatasize) + ")</nobr></td></tr>" +
		userDataRows +
	"</table>"+
	"</body>";
}

function getSectionNameFromID(id) {
    if (id.indexOf("System") == 0)
        return "System";
    else if (id.indexOf("Nodes") == 0)
        return "Nodes";
    else if (id.indexOf("Catalogs") == 0)
        return "Catalogs";
    else if (id.indexOf("Modules") == 0)
        return "Modules";
    else
        return "";
}

function updateSectionViews() {
    // Update section header texts
    var nc = 0;
    var snc = 0;
    var cc = 0;
    var scc = 0;
    var mc = 0;
    var smc = 0;
    var show;
    $("[id*='LineSelect']").each(function () {
        show = true;
        if ($(this).attr('id').indexOf("Node") >= 0) {
            nc++;
            if ("yes" == $(this).data("Selected"))
                snc++;
            else if ("Selected" == $('#NodesView').data('Show'))
                show = false;
        }
        else if ($(this).attr('id').indexOf("Catalog") >= 0) {
            cc++;
            if ("yes" == $(this).data("Selected"))
                scc++;
            else if ("Selected" == $('#CatalogsView').data('Show'))
                show = false;
        }
        else if ($(this).attr('id').indexOf("Module") >= 0) {
            mc++;
            if ("yes" == $(this).data("Selected"))
                smc++;
            else if ("Selected" == $('#ModulesView').data('Show'))
                show = false;
        }
        if (($target = $('#' + $(this).data('View'))).get(0)) {
            if (show)
                $target.slideDown('fast');
            else
                $target.slideUp('fast');
        }
    });
    $("#NodesLineText").text(nc + " Nodes, " + snc + " selected");
    $("#CatalogsLineText").text(cc + " Catalogs, " + scc + " selected");
    $("#ModulesLineText").text(mc + " Modules, " + smc + " selected");

}

function runUpdateFunctions() {
    $fullXML = $(latestXML);
    var compName;
    var compType;
    var funcName;
	var updateBox;
	
	for (var x in updateFunctionInfo) {
		var info = updateFunctionInfo[x];
	
		updateBox = $('#' + info.compType + "_" + info.compID  + 'LineUpdate');
		if (updateBox === undefined) {
			console.log("Couldn't find update checkbox for " + info.compType + " " + info.compID);
		}
		else {
			if (("yes" != updateBox.data("Updating")) && (info.compType != "System")) {
				console.log("Bypassing update of " + info.compType + " " + info.compID + " (Updating: "+updateBox.data("Updating")+")");
				continue;
			}
			//else 
			//	console.log("Updating " + x + " " + info.func);
		}
        $target = $('#' + info.target);
        try {
            eval(info.func + "($target, info.compID)");
        } catch (err) {}

	}
}

function loadTemplate(template, $target, templateName, compName, compType, openLink) {
	var cleanCompName = compName.replace(/\./g, '_');
	var templateText = compType + "_" + cleanCompName + "_" + templateName.replace(/\s+/g, '_');
    $fullXML = $(latestXML);
    console.log("Loading template for " + cleanCompName + ": " + template + " name: " + templateName + " comp: " + compName + " type: " + compType + " -->> " + $target.attr('id'));
    var html = loadURL(template);
	if (!html.length) {
		flashStatus("Could not load template file: " + template, 3000);
		return;
	}
	//console.log("<a href='/openelement?template=" + template + " target=blank>Open in new window</a>");

	var id = 0;
	var openTemplateURL = "";
	if ("System" == compType) {
		id = 1;
		if (openLink)
			openTemplateURL = "<table border=0 width=100%><tr><td align=right><a href='/loadelement?url=" + template + "' target='_blank'>Open in new window</a></td></tr></table>"
	}
	else if ("Node" == compType) {
		id = GetNodeID(compName);
		if (openLink)
			openTemplateURL = "<table border=0 width=100%><tr><td align=right><a href='/loadelement?url=" + template + "&node="+compName+"' target='_blank'>Open in new window</a></td></tr></table>"
		else
			openTemplateURL = "<table border=0 width=100%><tr><td width=99%></td><td class='EntryLineNotUpdating' id='Node_"+id+"LineUpdate' onclick='ToggleAllUpdates()'>&nbsp;&nbsp;</td></tr></table>";
	}
	else {
		id = GetComponentID(compName);
		if (openLink)
			openTemplateURL = "<table border=0 width=100%><tr><td align=right><a href='/loadelement?url=" + template + "&comp="+compName+"' target='_blank'>Open in new window</a></td></tr></table>"
		else
			openTemplateURL = "<table border=0 width=100%><tr><td width=99%></td><td class='EntryLineNotUpdating' id='Component_"+id+"LineUpdate' onclick='ToggleAllUpdates()'>&nbsp;&nbsp;</td></tr></table>";
	}
	if (id <= 0)
		return;

	html = openTemplateURL + html.replace(/Template/g, templateText);
    $target.html(html);
	$target.css('height', '100%');
	//    $target.css('resize', 'vertical');
//    $target.css('overflow', 'auto');

	// console.log("HTML: " + html);

    var loadFunc = "load" + templateText;
    var updateFunc = "update" + templateText;
    // console.log("Load: " + loadFunc + " Update: " + updateFunc);

	// var compEntry = componentMap[compID];
    try {
        eval(loadFunc + "($target, id)");
    } catch (err) {
		console.log("Error running load functions " + loadFunc + ": " + err.toString());
    }
    try {
        // eval(updateFunc + "($target, compID)");
        updateFunctionInfo[compType+"_"+compName] = { func: updateFunc, compID: id, compType: compType, target: $target.attr('id') };
        //if (updateFunctions.indexOf(updateFunc) < 0)
        //    updateFunctions.push(updateFunc);
    } catch (err) {
		console.log("Error running load/update functions for " + compName + "...");
    }
	//console.log("Updates are now: " + updateFunctions.toString());
}


