var foldMark = "-";
var unfoldMark = "+";
var switchStyle = "";
var labelStyle = "";
var headingStyle = "";
var headingStyleFolded = "";
var headingStyleUnfolded = "";
var headingStyleCommentedOut = "";

var pattern = ".";
var switchTagName = "BUTTON";
var scopeIds = new Array("left", "right");

function makeSwitchesBy() {
	var args = new Array();
	for (var i = 0; i < scopeIds.length; i++) {
		var scopeElement = document.getElementById(scopeIds[i]);
		if (!scopeElement) continue;
		args["scopeId"] = scopeIds[i];
		args["pattern"] = pattern;
		appendSwitchesBy(args);
	}
}

function foldContentsBy() {
	var args = new Array();
	for (var i = 0; i < scopeIds.length; i++) {
		var scopeElement = document.getElementById(scopeIds[i]);
		if (!scopeElement) continue;
		args["scopeId"] = scopeIds[i];
		args["pattern"] = pattern;
		switchModesBy(args);
	}
}

function appendSwitchesBy(args) {
	if (!args["scopeId"]) return false;
	var scopeElement = document.getElementById(args["scopeId"]);

	if (!args["pattern"]) args["pattern"] = pattern;	// if no pattern, switch all
	var regExp = new RegExp(args["pattern"], "i");

	var headingTagName = "H2";
	var headingElements = scopeElement.getElementsByTagName(headingTagName);

	for (var i = 0; i < headingElements.length; i++) {
		var headingElement = scopeElement.getElementsByTagName(headingTagName).item(i);

		// check if switch was already made
		var first = headingElement.firstChild;
		if (!first || first.nodeType == 1 && first.nodeName == switchTagName) continue;

		// check if the heading is commented-out
		var isCommentedOut = false;
		if (headingElement.innerHTML.substr(0,4) == "<!--") isCommentedOut = true;
		var aFirstChild = headingElement.firstChild;
		if (aFirstChild.nodeType == 8) isCommentedOut = true;	//Node.COMMENT_NODE
		if (isCommentedOut) {
			continue;
		}
		
		var theInnerText = _getInnerText(headingElement);
		if (isWhiteSpace(theInnerText)){continue;}

		// check if matched
		if (!theInnerText.match(regExp)) continue;

		// make switch and label
		if (headingElement.innerHTML) {
			// get headingChildNodes, create switch and append them into a new lable
			var oldInnerHTML = headingElement.innerHTML;
			switchTagName.toLowerCase();
			var switchStyleAttr = "";
			if (switchStyle != "") switchStyleAttr = ' style="' + switchStyle + '"';
			var labelStyleAttr = "";
			if (labelStyle != "") labelStyleAttr = ' style="' + labelStyle + '"';
			var newInnerHTML =
				'<' + switchTagName +
				' class="switch"' +
				' name="switch-' + i + '"' +
				' onClick="switchMode(this)"' +
				switchStyleAttr +
				'>' +
				foldMark +
				'</' + switchTagName + '>' +
				'<label' +
				' class= "switch-label"' +
				' for="switch-' + i + '"' +
				labelStyleAttr +
				'>' +
				oldInnerHTML +
				'</label>';
			headingElement.innerHTML = newInnerHTML;
//			if (!res) return;
		} else {
			// append the all childNodes into a new labelElement
			var labelElement = document.createElement("LABEL");
			var headingChildNodes = headingElement.childNodes;
			for (var k = 0; k < headingChildNodes.length; k++) {
				labelElement.appendChild(headingChildNodes[k]);
			}

			// - create switch and append it into heading
			var switchElement = document.createElement(switchTagName);
			headingElement.appendChild(switchElement);

			// append label into heading
			headingElement.appendChild(labelElement);

			// - set attributes
			_setAttribute(switchElement, "class", "switch");
			_setAttribute(switchElement, "name", "switch-" + i);
			switchElement.onclick = function() { switchMode(this); };
			_setAttribute(switchElement, "style", switchStyle);

			_setAttribute(labelElement, "class", "switch-label");
			_setAttribute(labelElement, "for", "switch-" + i);
			_setAttribute(labelElement, "style", labelStyle);
		}

		// - set heading class	(for style)
		_setAttribute(headingElement, "class", "unfolded");
	}
}

function isWhiteSpace(theInnerText){
	return (theInnerText.match(/^[　\s]+$/));
}
function switchModesBy(args) {
	if (!args["scopeId"]) return false;
	var scopeElement = document.getElementById(args["scopeId"]);

	if (!args["pattern"]) args["pattern"] = pattern;	// if no pattern, switch all
	var regExp = new RegExp(args["pattern"], "i");

	var headingElements = scopeElement.getElementsByTagName("H2");
	for (var i = 0; i < headingElements.length; i++) {
		var headingElement = headingElements[i];
		if (!headingElement.innerHTML||headingElement.innerHTML.substr(0,4) == "<!--") continue;
		if (headingElement.nodeType == 8) continue;	// 8: Node.COMMENT_NODE
		var switchElement;
		var switchElements = headingElement.getElementsByTagName(switchTagName);
		for (var j = 0; j < switchElements.length; j++) {
			switchElement = switchElements[j];
			var theClass = _getAttribute(switchElement, "class");
			if (theClass && theClass == "switch") {
				break;
			}
		}
		if (!switchElement) continue;

		// get labelElement and check if matched with the given pattern
		var labelElement = headingElement.getElementsByTagName("LABEL").item(0);
		if (!labelElement) continue;
		var theInnerHTML = labelElement.innerHTML;
		if (!theInnerHTML||!theInnerHTML.match(regExp)) continue;

		switchMode(switchElement);
	}
}

function switchMode(switchElement) {
	var headingElement = switchElement.parentNode;	// = a heading

	// get firstTargetElement
	var firstTargetElement = _getNextElement(headingElement);

	// get oldDisplayMode and set newDisplayMode
	var oldDisplayMode = firstTargetElement.style.display;
	var newDisplayMode = (oldDisplayMode == "none") ? "block" : "none";

	// switch mode
	var targetElement = firstTargetElement;
	while (targetElement) {
		var targetTagName = targetElement.nodeName;
		if (targetTagName == "H2") break;
		targetElement.style.display = newDisplayMode;
		targetElement = _getNextElement(targetElement);
	}

	// switch marker
	var newMarker = (newDisplayMode == "none") ? unfoldMark : foldMark;
	if (document.createTextNode) {
		switchElement.firstChild.nodeValue = newMarker;
	} else {
		switchElement.innerText = newMarker;
	}

	// switch heading attributes
	var newClass = (newDisplayMode == "none") ? "folded" : "unfolded";
	_setAttribute(headingElement, "class", newClass);
}


var counterPrefix = "(";
var counterPostfix = ")";
var counterStyle = "letter-spacing:normal;";

var counterTagName = "SPAN";
var counterClass = "counter";

var scopeIds = new Array("left", "right");
var headingTagName = "H2";
var pattern = ".";
var countBroadly = false;

function countItemsBy() {
	var regExp = new RegExp(pattern);

	for (var i = 0; i < scopeIds.length; i++) {
		var scopeElement = document.getElementById(scopeIds[i]);
		if (!scopeElement) continue;

		var headingElements = scopeElement.getElementsByTagName(headingTagName);
		for (var j = 0; j < headingElements.length; j++) {
			var headingElement = headingElements[j];
			var theInnerText = _getInnerText(headingElement);
			if (!theInnerText||!theInnerText.match(regExp)) continue;

			var n = _getNumOfItems(headingElement);

			if(headingElement.innerHTML) {
				var oldInnerHTML = headingElement.innerHTML;
				var counterStyleAttr = "";
				if (counterStyle != "") counterStyleAttr = ' style="' + counterStyle + '"';
				var newInnerHTML =
					oldInnerHTML +
					'<' + counterTagName +
					' class="' + counterClass + '"' +
					counterStyleAttr +
					'>' +
					counterPrefix + n + counterPostfix +
					'</' + counterTagName + '>';
				headingElement.innerHTML = newInnerHTML;
			} else {
				var counterElement = document.createElement(counterTagName);
				counterElement.appendChild(document.createTextNode(counterPrefix));
				counterElement.appendChild(document.createTextNode(n));
				counterElement.appendChild(document.createTextNode(counterPostfix));
				headingElement.appendChild(counterElement);
				_setAttribute(counterElement, "class", counterClass);
				if (counterStyle != "") {
					_setAttribute(counterElement, "style", counterStyle);
				}
			}
		}
	}
}

function _getNumOfItems(headingElement) {
	var n = 0;
	var targetElement = _getNextElement(headingElement);
	while(targetElement) {
		if (targetElement.nodeName.match(/^H.$/, "i")) break;

		var LIs = targetElement.getElementsByTagName("LI");
		var dn = LIs.length;
		if (dn == 0 && countBroadly) dn = 1;
		n += dn;
		targetElement = _getNextElement(targetElement);
	}
	return n;
}
