(function($){

	$(window).load(function(event) {
		// Tree expansion
		$("table#viewTable").treeExp();
	});

	$.fn.lvlctl = function () {
		return this.find('.lvlctl');
	};

	$.fn.getLvl2 = function () {
		var oFound = this.lvlctl().attr('lvl');
		return parseInt(oFound || '-1' , 10);
	};

	// Tree expansion：下位展開関数
	$.fn.treeExp = function(opts) {
		var settings , rowFullExp , rowSubExp ;
		settings = {
			sFetching : "fetching",
			sFetched	: "fetched",
			sCollapsed: "collapsed",
			sExpanded : "expanded",
			sNoSub		: "nosub",
			sSTreeUrl : "",
			sSTreeUFn : "h_child_search_jsp",
			sTPlusImg : "",
			sTMinusImg: "",
			sTLeafImg : "",
			sTPlusFn	: "h_img_collapsed",
			sTMinusFn : "h_img_expanded",
			sTLeafFn	: "h_img_nosub"
		};
		$.extend(settings, $.hybs.defaults);

		rowSubExp = function (jTarget, hOpts) {
			var bRet , pars , jTr , bUnitRow , jTab , bExpanded , jRun , nLvl , nMaxInt , nHasSub , sSubSearchUrl , mParams , sVals , sKeys , asKeys , nKeysLen , oRowInfo ;

			bRet = true;
			pars = { bForceExp:false, bHeaderFix:true };
			$.extend(pars, hOpts || {});

			// Get Tree Images
			if(!settings.sTPlusImg ) settings.sTPlusImg	= $.hybs.getHValue(settings.sTPlusFn );
			if(!settings.sTMinusImg) settings.sTMinusImg = $.hybs.getHValue(settings.sTMinusFn);
			if(!settings.sTLeafImg ) settings.sTLeafImg	= $.hybs.getHValue(settings.sTLeafFn );
 
			// Turn jTr to tr or tbody
			jTr = $.hybs.getHybsTr(jTarget.parents("tr:first"));
			bUnitRow = jTr.is("tr");
			jTab = jTarget.parents("table:first");

//			if(jTr.hasClass(settings.sFetching)) ;				// 1.Fetching now...
//			else if(jTr.hasClass(settings.sNoSub)) ;			// 2.No Child
//			else if(jTr.hasClass(settings.sFetched)) {			// 3.Has Feched
			if(jTarget.hasClass(settings.sFetching)) {}				// 1.Fetching now...
			else if(jTarget.hasClass(settings.sNoSub)) {} 			// 2.No Child
			else if(jTarget.hasClass(settings.sFetched)) {			// 3.Has Feched
//				var bExpanded = jTr.hasClass(settings.sExpanded);
				bExpanded = jTarget.hasClass(settings.sExpanded);
				// 下位展開かつ下位強制展開(shift押しながらクリック)の場合、何もしない
				if(bExpanded && pars.bForceExp) {}
				else {
					// 下位展開と隠しの処理
					jRun = jTr.next();
					nLvl = jTr.getLvl2();
					nMaxInt = Math.floor(Number.MAX_VALUE);
					nCloseLvl = nMaxInt;
//					var nHasSub;

					while(jRun[0]) {
						// break when there exists nothing in the lower level
						nRunLvl = jRun.getLvl2();
						// 処理行のレベルがクリックした行のレベルより小さい場合、終了
						if(nLvl >= nRunLvl) break;

						if(bExpanded) jRun.hide();
						else {
							// ここは下位展開処理
//							if(jRun.hasClass(settings.sCollapsed)) {
							if(jRun.lvlctl().hasClass(settings.sCollapsed)) {
								// 未展開行の場合、その行レベルを保存しとく
								if(nCloseLvl > nRunLvl) nCloseLvl = nRunLvl;
							}
							else {
								// 展開行の場合、その子のレベルを無視する
								if( nCloseLvl >= nRunLvl) nCloseLvl = nMaxInt;
							}

							if( nCloseLvl >= nRunLvl) jRun.show();
						}

						nHasSub = true;
						jRun = jRun.next();
					}
					if(bExpanded) {
						// 元は下位展開の場合、下位を隠した状態に変更
						if(nHasSub) {
//							jTr.removeClass(settings.sExpanded).addClass(settings.sCollapsed);
							jTarget.removeClass(settings.sExpanded).addClass(settings.sCollapsed);
							jTarget.attr('src', settings.sTPlusImg);
						}
					}
					else {
						//元は下位隠しの場合、下位を展開状態に変更
//						jTr.removeClass(settings.sCollapsed).addClass(settings.sExpanded);
						jTarget.removeClass(settings.sCollapsed).addClass(settings.sExpanded);
						jTarget.attr('src', settings.sTMinusImg);
					}
					// resize view range
					if(pars.bHeaderFix) jTab.resizeView();
				}
			}
			else {																	// 4.Do fecth
				//下位展開のURLを取得
				sSubSearchUrl = settings.sSTreeUrl;
				if(!sSubSearchUrl && settings.sSTreeUFn) sSubSearchUrl = $.hybs.getHValue(settings.sSTreeUFn);
				if(!sSubSearchUrl) {
					$.hybs.ogAlert("URL is not sepcified!");
					bRet = false;
				}
				else {
					// Construct parameters
					mParams = {};
					sVals = jTarget.attr("vals");
					if(sVals) {
						//サーバーに渡すパラメータを準備する
						sKeys = jTarget.attr("keys");
						asKeys = (sKeys)? sKeys.split(",") : [];
						nKeysLen = asKeys.length;

						// Map parameter data
						$.each(sVals.split(","), function(n, value) {
							mParams[(n < nKeysLen) ? asKeys[n] : 'key' + n] = value;
						});

						// Add h_rowSel to parameter
						oRowInfo = {};
						if(!mParams[settings.sHybsSel]) oRowInfo[settings.sHybsSel] = jTr.attr(settings.sHybsRid);
						if(!mParams[settings.sHybsCmd]) oRowInfo[settings.sHybsCmd] = 'NEW';
						if(!mParams[settings.sNoTsKey]) oRowInfo[settings.sNoTsKey] = 'true';

						$.extend(mParams, oRowInfo);
					}

					// Fetch data from server
					$.ajax({
						url	: sSubSearchUrl,
						data : mParams,
						type : 'POST',
						async: false,
						error:
							function (xhr, status, e) {
								bRet = false;
								$.hybs.ogLog(status + '\n' + xhr.responseText);
								$.hybs.ogAlert(status + '<br/>' + xhr.responseText);
							},
						success:
							function(data) {
								var match , sText , jNext , nNoColId , aOgClrCls , sRowClrCls , jRun ;
								// Test tbody is a part of the html
								if(bUnitRow)
									// 2009/06/29 tbody入れ子解消
									// match = /<tbody>([\S\s]*)<\/tbody>/m.exec(data);
									match = /(<tbody[^>]*>[\S\s]*<\/tbody>)/m.exec(data);
								else {
									// 2009/06/29 tbody入れ子解消
									// match = /<tbody>([\S\s]*)<\/tbody>/m.exec(data);
									match = /(<tbody[^>]*>[\S\s]*<\/tbody>)/m.exec(data);
								}

								sText = "";
								if(match) { sText = $.trim(match[1]); }

								if(!sText) {
									// 下位がなかったら、枝のマークをつける
									jTarget.attr('src', settings.sTLeafImg);
//									jTr.removeClass(settings.sCollapsed)
									jTarget.removeClass(settings.sCollapsed)
										 .addClass(settings.sFetched + ' ' + settings.sExpanded + ' ' +settings.sNoSub);
								}
								else {
									jNext = jTr.next();
									// クリックした行の下にデータを追加
//									jTr.removeClass(settings.sFetching + ' ' + settings.sCollapsed)
//										 .addClass(settings.sFetched + ' ' + settings.sExpanded)
//										 .after(sText);
									jTarget.removeClass(settings.sFetching + ' ' + settings.sCollapsed)
										 .addClass(settings.sFetched + ' ' + settings.sExpanded);
									jTr.after(sText);

									// Turn to minus mark
									jTarget.attr('src', settings.sTMinusImg);

									nNoColId = $.hybs.getNoColId(jTab);
									aOgClrCls = ['row_0','row_1','row_hilight'];
									sRowClrCls = $.grep(aOgClrCls, function (c) {return jTr.hasClass(c);})[0];
									jRun = jTr.next();
									// 下位行にクラス属性を追加
									while(jRun[0] && (jRun[0] != jNext[0])) {
//										jRun.addClass(settings.sCollapsed)
//												.removeClass(aOgClrCls.join(" "))
//												.addClass(sRowClrCls);
										jRun.lvlctl().addClass(settings.sCollapsed);
										jRun.removeClass(aOgClrCls.join(" "))
												.addClass(sRowClrCls);

										//画面の行番号を削除
										if(0 <= nNoColId) jRun.find('td:nth(' + nNoColId + ')').empty();

										jRun = jRun.next();
									}

								}
								// resize view range
								if(pars.bHeaderFix) jTab.resizeView();
							}
					});
				}
			}

			return bRet;
		};

		//選択行の下位を全て展開する関数
		rowFullExp = function (jTarget) {
				var jHybsTr , nBaseLvl , jRunTr , jLvlCtl ;

				jHybsTr = $.hybs.getHybsTr(jTarget.parents("tr:first"));
				nBaseLvl = jHybsTr.getLvl2();
				jRunTr = jHybsTr;
				jLvlCtl = jTarget;
				while(true) {
					if(!rowSubExp(jLvlCtl, { bForceExp:true, bHeaderFix:false })) break;
					jRunTr = jRunTr.next();
					if(0 == jRunTr.size()) break;
					if(nBaseLvl >= jRunTr.getLvl2()) break;
					jLvlCtl = jRunTr.lvlctl();
				}
				// Reposition Header
				jHybsTr.parents("table:first").resizeView();
		};

		return this.each(function() {
			var oTab = this;
			$(oTab).click(function(evt) {
				var jTarget = $(evt.target);
				// Click on level control
				if(jTarget.is(".lvlctl")) {
					// シフトキーを押す時、下位を全て展開する
					if(evt.shiftKey) { rowFullExp(jTarget); }
					else { rowSubExp(jTarget); }
				}
			});

		});
	};

})(jQuery);

