/**
 * カテゴリツリーを作成するクラスです。<br />
 * カテゴリツリー一つに対して一つのインスタンスを作成します。<br />
 * 初期化はコンストラクタによって行われますが、描画はdrawメソッドを呼び出すことで行われます。
 * 
 * @namespace com.nec.jp.ngsf.wiki
 * @class SDWikiCategory
 * @uses YAHOO.widget.TreeView
 * @param containerId {string} カテゴリツリーを作成するコンテナ（divエレメント）のID
 * @param cookieId {string} Cookieに値を保存するためのID
 * @constructor
 */
com.nec.jp.ngsf.wiki.SDWikiCategory = function(containerId, cookieId) {
	if (containerId) {
		if (cookieId) {
			this.initialize(containerId, cookieId);
		} else {
			this.initialize(containerId);
		}
	}
};
com.nec.jp.ngsf.wiki.SDWikiCategory.prototype =
	Object.extend(new com.nec.jp.ngsf.wiki.SDWikiCategoryTree, {
	
	/**
	 * 追加のイベントをカテゴリツリーに設定します。<br />
	 * カテゴリプラグインではCookieによる開閉状態の維持をするためのイベントを設定します。
	 * （Cookieの生存期間はセッション期間となります）
	 * @method _setCustomEvent
	 * @param tree {Yahoo.widget.TreeView} イベントを設定するツリーオブジェクト。
	 * @private
	 */
	_setCustomEvent: function(tree) {
		var containerElm = document.getElementById(this.containerId);
		
		// ファイルIDの設定
		var fileIdElm = document.getElementsByClassName('fileId', containerElm);
		if (fileIdElm && fileIdElm[0]) {
			this.tree.fileId = fileIdElm[0].value;
		}
		
		// カテゴリプラグインIDの設定
		var categoryIdElm = document.getElementsByClassName('categoryId', containerElm);
		if (categoryIdElm && categoryIdElm[0]) {
			this.tree.categoryId = categoryIdElm[0].value;
		}
		
		// ノード開閉時のCookie保存処理を追加
		if (this.cookieId && (this.cookieId != '')) {
			tree.cookieId = this.cookieId;
			
			// 開いたときの処理
			tree.onExpand = function(node) {
				// Cookieから読み込み
				var cookieValue = com.nec.jp.ngsf.wiki.SDWikiCategory.getCookie(this.cookieId);
				var openCategories = cookieValue.split(':');
				
				// 今開いたカテゴリを配列に追加
				openCategories[openCategories.length] = node.fullName;
				
				// 配列の整理
				var newCookieValue = com.nec.jp.ngsf.wiki.SDWikiCategory.getCookieString(openCategories);
				
				// Cookieに保存する値が閾値を超えた場合は古いものを削除
				if (encodeURIComponent(newCookieValue).length > 3000) {
					newCookieValue = newCookieValue.substring(newCookieValue.indexOf(":") + 1);
				}
				
				// Cookieの保存
				com.nec.jp.ngsf.wiki.SDWikiCategory.setCookie(this.cookieId, newCookieValue);
			};
			
			// 閉じたときの処理
			tree.onCollapse = function(node) {
				// Cookieから読み込み
				var cookieValue = com.nec.jp.ngsf.wiki.SDWikiCategory.getCookie(this.cookieId);
				var openCategories = cookieValue.split(':');
				
				for (var i = 0; i < openCategories.length; i++) {
					if (openCategories[i] == node.fullName) {
						openCategories[i] = "";
						
						// ルート直下ではない場合、親のカテゴリは開いたままとする
						if (node.fullName.lastIndexOf("/") > 0) {
							openCategories[i] = node.fullName.substring(0, node.fullName.lastIndexOf("/"));
						}
					} else if (openCategories[i].indexOf(node.fullName) == 0) {
						// 閉じようとしているカテゴリのサブカテゴリも閉じる
						if (openCategories[i].substring(node.fullName.length, node.fullName.length + 1) == "/") {
							openCategories[i] = "";
						}
					}
				}
				
				// 配列の整理
				var newCookieValue = com.nec.jp.ngsf.wiki.SDWikiCategory.getCookieString(openCategories);

				// Cookieに保存する値が閾値を超えた場合は古いものを削除
				if (encodeURIComponent(newCookieValue).length > 3000) {
					newCookieValue = newCookieValue.substring(newCookieValue.indexOf(":") + 1);
				}
				
				// Cookieの保存
				com.nec.jp.ngsf.wiki.SDWikiCategory.setCookie(this.cookieId, newCookieValue);
			};
		}
	},
	
	/**
	 * ノードデータの非同期読み込みを行います。<br />
	 * 読み込み終了後、ノードを子として追加します。
	 * @method _loadNodeData
	 * @param node {YAHOO.widget.Node} 子のデータを読み込むノード。
	 * @param fnLoadComplete {function} 終了時の処理関数。（Yahoo UI TreeViewでセットされます）
	 * @private
	 */
	_loadNodeData: function(node, fnLoadComplete) {
		// DWR非同期処理を呼ぶ
		WikiPluginController.processAction("sdwiki_category", new Array("getNodeData", node.fullName, node.tree.fileId, node.tree.categoryId),
				function(oResponse) {
			if (oResponse != null && oResponse.length > 0) {
				var nodeData = eval(oResponse[0]);
				node._appendNode(nodeData[0][4], node);
				fnLoadComplete();
			}
		});
	}
});

/**
 * 画面上に配置されている全てのカテゴリツリーを初期化します。
 * @method com.nec.jp.ngsf.wiki.SDWikiCategory.initAll
 * @static
 */
com.nec.jp.ngsf.wiki.SDWikiCategory.initAll = function() {
	// コンテナを取得
	var containerElms = document.getElementsByClassName('gleanfeed-wiki-plugin-category-container');
	
	// 各カテゴリツリーを初期化
	var ids = [];
	for (var i = 0; i < containerElms.length; i++) {
		var containerElm = containerElms[i];
		var containerId = containerElm.id;
		
		// IDが重複している場合は振りなおす
		for (var j = 0; j < ids.length; j++) {
			if (containerElm && ids[j] == containerElm.id) {
				containerElm.id = containerElm.id + '-' + i;
				break;
			}
		}
		
		// カテゴリツリーの作成
		var category = new com.nec.jp.ngsf.wiki.SDWikiCategory(containerElm.id, containerId);
		category.draw();
		
		ids[ids.length] = containerElm.id;
	}
};

/**
 * Cookieから値を取得します。
 * @method com.nec.jp.ngsf.wiki.SDWikiCategory.getCookie
 * @param id {string} 取得する値の名前
 * @static
 */
com.nec.jp.ngsf.wiki.SDWikiCategory.getCookie = function(id) {
	var i, index, arr;
	if (document.cookie!=null && document.cookie!="") {
		var str = decodeURIComponent(document.cookie);
		arr = str.split(";");
		for(i = 0; i < arr.length; i++) {
			index = arr[i].indexOf("=");
			if(arr[i].substring(0, index) == id || arr[i].substring(0, index) == " " + id) {
				return arr[i].substring(index + 1);
			}
		}
	}
	return "";
};

/**
 * Cookieに値を設定します。
 * @method com.nec.jp.ngsf.wiki.SDWikiCategory.setCookie
 * @param id {string} 設定する値の名前
 * @param value {string} 設定する値
 * @static
 */
com.nec.jp.ngsf.wiki.SDWikiCategory.setCookie = function(id, value) {
	document.cookie = id + '=' + encodeURIComponent(value) + ";";
};

/**
 * 開いているカテゴリを保持した配列からCookieに保存する文字列を作成します。
 * @method com.nec.jp.ngsf.wiki.SDWikiCategory.getCookieString
 * @param openedCategories {string[]} 開いているカテゴリを保持した配列
 * @static
 */
com.nec.jp.ngsf.wiki.SDWikiCategory.getCookieString = function(openedCategories) {
	var categories = [];
	
	for (var i = 0; i < openedCategories.length; i++) {
		var opened = openedCategories[i];
		
		// タイトルが入っている場合のみ処理する
		if (opened) {
			// 配列が0件の場合は無条件にセット
			if (categories.length == 0) {
				categories[0] = opened;
				continue;
			}
			
			//
			var doAppend = true;
			for (var j = 0; j < categories.length; j++) {
				var target = categories[j];
				
				if (opened == target) {
					// 既に追加されている場合は追加しない
					doAppend = false;
					break;
				} else if (opened.indexOf(target) == 0) {
					// 追加しようとしているカテゴリが、既に追加されているカテゴリのサブカテゴリかどうかチェック
					if (opened.substring(target.length, target.length + 1) == "/") {
						// サブカテゴリだった場合は親のカテゴリ定義は必要ない
						categories[j] = "";
					}
				} else if (target.indexOf(opened) == 0) {
					// 既に追加されているカテゴリが、追加しようとしているカテゴリのサブカテゴリかどうかチェック
					if (target.substring(opened.length, opened.length + 1) == "/") {
						// サブカテゴリだった場合は追加しない
						doAppend = false;
						break;
					}
				}
			}
			
			// 追加
			if (doAppend == true) {
				categories[categories.length] = opened;
			}
		}
	}
	
	// 配列を「:」区切りの文字列に変換
	var cookieString = "";
	
	for (var i = 0; i < categories.length; i++) {
		if (categories[i]) {
			cookieString = cookieString + ":" + categories[i];
		}
	}
	
	if (cookieString.length > 0) {
		cookieString = cookieString.substring(1);
	}
	
	return cookieString;
}

// ツリーの初期化をwindow.onloadイベントに追加
Event.observe(window, "load", com.nec.jp.ngsf.wiki.SDWikiCategory.initAll);
