/*
 * author: hongqiang.cui
 * produce: 2009.07.29
 * function: service for productline's auto calculate price!
 * note: modify premise that understand it. TIA.
 */

//major js object
function CalendarCtl(pricePerDateLs, nowServerDate){
	this.nowServerDate = nowServerDate;	// this is value of current date from server side. eg: var nowServerDate = {month: 7, date:29, year: 2009};
	// per-day price table, this is a two-dimensional array, one is date info, the other is price info.
	/* this is a JSON object. format pattern:
	 * 	var pricePerDateJSON = {
	 * 		month:	7,
	 * 		date:	29,
	 * 		year:	2009,
	 * 		price:	888
	 * 	};
	 * eg: this is 888 yuan of price at 2009-7-29 day.
	 */
	this.pricePerDateLs = pricePerDateLs;
	this.weekLs = ["\u661f\u671f\u65e5", "\u661f\u671f\u4e00", "\u661f\u671f\u4e8c", "\u661f\u671f\u4e09", "\u661f\u671f\u56db", "\u661f\u671f\u4e94", "\u661f\u671f\u516d"];
	this.frameTable = document.createElement("TABLE");
	this.constRows = 3;
	this.constCells = 9;
	this.DyDataTab = "DyDataTab_ID";	// this is a area of dynamic data for price per-day. thus it's also this CalendarCtl major business function!
	this.downwardTabEx = null; // this is a point that down forward CalendarTabEx.
	// they are up or down turning element.
	this.upClickEle = "upClickEle_ID";
	this.downClickEle = "downClickEle_ID";
	
}

//tableEx object
function CalendarTabEx(parentObjEx){
	this.parentObjEx = parentObjEx;	// the point that CalendarCtl embed this component.
	this.festivalLs = [["1-1", "\u5143\u65e6"], ["2-14", "\u60c5\u4eba\u8282"], ["3-8", "\u5987\u5973\u8282"], ["3-12", "\u690d\u6811\u8282"], ["4-1", "\u611a\u4eba\u8282"], ["4-5", "\u6e05\u660e"],
	    	           ["5-1", "\u52b3\u52a8\u8282"], ["5-4", "\u9752\u5e74\u8282"], ["6-1", "\u513f\u7ae5\u8282"], ["6-16", "\u7aef\u5348\u8282"], ["7-1", "\u5efa\u515a\u65e5"], ["8-1", "\u5efa\u519b\u8282"],
	    	           ["9-10", "\u6559\u5e08\u8282"], ["9-27", "\u65c5\u6e38\u65e5"], ["10-1", "\u56fd\u5e86\u8282"], ["11-28", "\u611f\u6069\u8282"], ["12-25", "\u5723\u8bde\u8282"]];	
	this.elementTabEx = document.createElement("TABLE");
	this.constNestRows = 6;
	this.constNestCells = 8;
	this.startDisplayPoint = null;	// this is customer can visual lately depart date.
	this.endDisplayPoint = null;	// this is customer can visual last depart date.
	this.flagOriginal = true;	// this page is or not contain multi-month.
	this.flagHasPrice = true;
	this.downwardTrEx = null;	// this is a point that down forward CalendarTrEx.
}

//trEx object
function CalendarTrEx(parentTabEx){
	this.parentTabEx = parentTabEx;	// reference pointer.
	//this.itemTrEx = document.createElement("TR");		// this is a hidden expand point, while table's row specify some special properties.
	this.allTdExLs = [];	//	this is all tdEx that of priceDate.
	this.turningMaximum  = 2;	// this is default value that max number of times  that turning as possible as. 
	//at the moment, turning page's head and tail array index.
	this.turningIndex = 0;
	this.enumHeadTailLs = [[]];
}

//tdEx object
function CalendarTdEx(parentTrEx){
	this.parentTrEx = parentTrEx;	// reference pointer.
	this.itemTdEx = document.createElement("TD");
	this.dateInfo = null;
	this.festivalText = "";
	this.curdayPrice = "";
}

// init CalendarTdEx show date.
CalendarTdEx.prototype.fillTableCell = function(htmlObj){
	with(this){
		itemTdEx.innerHTML = "<span style='color:#FF0000'>" + festivalText + "</span>&nbsp;" + dateInfo.getDate() + "<br/>";
		itemTdEx.innerHTML += "<span class='price'>\uffe5" + ((curdayPrice + "").length > 3 ? 
				(curdayPrice + "").substring(0, (curdayPrice + "").length - 3).concat(",").concat((curdayPrice + "").substr((curdayPrice + "").length - 3)) : curdayPrice)
				+ "\u8d77</span>";
	}
	htmlObj.innerHTML = this.itemTdEx.innerHTML;
	htmlObj.style.cursor = "hand";
	htmlObj.width = "60";
	// this is very important interface for invoke outer control. AttachEvent!!!
	htmlObj.setAttribute("dateTime", this.dateInfo.getTime());
	htmlObj.onclick = function(){
		if(typeof(Calendar) == "function" && typeof(fillTextFlag) != "undefined"){
			journeyNo = 0;
			fillTextFlag = "LEAVEDATEFLAG";
			var attriDate = new Date(this.dateTime);
			var paramDate = attriDate.getFullYear() + (attriDate.getMonth() < 9 ? "-0" : "-") + (attriDate.getMonth() + 1) +
			(attriDate.getDate() < 10 ? "-0" : "-") + attriDate.getDate();
			control_txt(paramDate);		// core function finished!!!
		}
		showpop();
	};
	htmlObj.onmouseover = function(){
		this.bgColor = "#F7FBE4";
	}
	htmlObj.onmouseout = function(){
		this.bgColor = "#FFFFFF";
	}
};

//init CalendarTrEx associate data. eg: allTdExLs
CalendarTrEx.prototype.initAssociateDate = function(){
	//fill allTdExLs[[]]. One dimension index is month value, One dimension value is cell info.
	var refPricePerDateLs = this.parentTabEx.parentObjEx.pricePerDateLs;
	var refFestivalLs = this.parentTabEx.festivalLs;
	for(var i = 0; i < refPricePerDateLs.length; i ++){
		if(typeof(this.allTdExLs[refPricePerDateLs[i].month]) == "undefined")	this.allTdExLs[refPricePerDateLs[i].month] = [];
		var curCalendarTdEx = new CalendarTdEx(this);
		curCalendarTdEx.dateInfo = new Date(refPricePerDateLs[i].year, refPricePerDateLs[i].month - 1, refPricePerDateLs[i].date);
		var matchText = refPricePerDateLs[i].month + "-" + refPricePerDateLs[i].date;
		for(var j = 0; j < refFestivalLs.length; j ++){
			if(matchText == refFestivalLs[j][0]){
				curCalendarTdEx.festivalText = refFestivalLs[j][1];
				break;	// One day the most One festivalLs.
			}
		}
		curCalendarTdEx.curdayPrice = refPricePerDateLs[i].price;
		
		this.allTdExLs[refPricePerDateLs[i].month][refPricePerDateLs[i].date] = curCalendarTdEx;	// index large acreage to apply.
	}
	//fill enumHeadTailLs[[]]. One dimension index is turningIndex, One dimension value is startDisplayPoint and endDisplayPoint.
	this.enumHeadTailLs[0][0] = this.parentTabEx.startDisplayPoint;
	this.enumHeadTailLs[0][1] = this.parentTabEx.endDisplayPoint;
	for(var c = 0; c < this.turningMaximum; c ++){
		var nextDate = new Date(this.enumHeadTailLs[this.enumHeadTailLs.length - 1][1].getTime() + 24*60*60*1000);
		for(var i = 0; i < refPricePerDateLs.length; i ++){
			var tempDate = new Date(refPricePerDateLs[i].year, (refPricePerDateLs[i].month - 1), refPricePerDateLs[i].date);
			if(new Date(nextDate.getFullYear(), nextDate.getMonth(), 1) <= tempDate &&
					tempDate < new Date(nextDate.getFullYear(), (nextDate.getMonth() + 1), 1)){
				if(typeof(this.enumHeadTailLs[this.enumHeadTailLs.length]) == "undefined")	this.enumHeadTailLs[this.enumHeadTailLs.length] = [];
				this.enumHeadTailLs[this.enumHeadTailLs.length - 1][0] = new Date(nextDate.getFullYear(), nextDate.getMonth(), 1);
				this.enumHeadTailLs[this.enumHeadTailLs.length - 1][1] = new Date(new Date(nextDate.getFullYear(), (nextDate.getMonth() + 1), 1).getTime() - 24*60*60*1000);
				break;
			}
		}
	}
	this.turningMaximum = this.enumHeadTailLs.length - 1;	//actual counts.
};

//write CalendarTabEx into it's parent container. deal with dynamic data for price per-day!
CalendarTabEx.prototype.writeActiveX = function(){
	//draw dynamic data
	var transientDate = this.downwardTrEx.enumHeadTailLs[this.downwardTrEx.turningIndex][0]; //this.startDisplayPoint;
	var transientDateEnd = this.downwardTrEx.enumHeadTailLs[this.downwardTrEx.turningIndex][1];	//this.endDisplayPoint;
	//alert(transientDate.toLocaleString() + " -- " + transientDateEnd.toLocaleString());
	//page turning point
	var transientDatePrice = this.downwardTrEx.allTdExLs;
	var transientFestival = this.festivalLs;
	var dayIndex = transientDate.getDay();
	//reset data
	for( ; this.elementTabEx.rows.length > 0; ){
		for(; this.elementTabEx.rows(0).cells.length > 0; )
			this.elementTabEx.rows(0).deleteCell(0);
		 this.elementTabEx.deleteRow(0);
	}
	for(var r = 0; r < this.constNestRows; r ++){
		var curTrobj = this.elementTabEx.insertRow();
		for(var c = 0; c < this.constNestCells; c ++){
			var curTdobj = curTrobj.insertCell();
			this.parentObjEx.fillProperties(curTdobj, [["width", 55], ["height", 35], ["bgColor", "#FFFFFF"]]);
			//first-column 
			if(c%this.constNestCells == 0 && transientDate <= transientDateEnd)	curTdobj.innerHTML = transientDate.getFullYear() + "\u5e74<br/>" + (transientDate.getMonth() + 1) + "\u6708";
			//blank-column
			else if((r == 0 && c < (dayIndex + 1)) || transientDate > transientDateEnd)	curTdobj.innerHTML = "&nbsp;";
			//normal-column
			else{
				if(typeof(transientDatePrice[transientDate.getMonth() + 1]) != "undefined" && 
						typeof(transientDatePrice[transientDate.getMonth() + 1][transientDate.getDate()]) != "undefined"){
					transientDatePrice[transientDate.getMonth() + 1][transientDate.getDate()].fillTableCell(curTdobj);
				}
				else{
					var matchText = (transientDate.getMonth() + 1) + "-" + transientDate.getDate();
					for(var j = 0; j < transientFestival.length; j ++){
						if(matchText == transientFestival[j][0]){
							curTdobj.innerHTML = "<span style='color:#FF0000'>" + transientFestival[j][1] + "</span>&nbsp;";
							break;	// One day the most One festivalLs.
						}
					}
					curTdobj.innerHTML += transientDate.getDate();
				}
				//auto-increment
				transientDate = new Date(transientDate.getTime() + 24*60*60*1000);
				//cell set style
				this.parentObjEx.fillProperties(curTdobj, [["width", 60], ["align", "right"], ["vAlign", "top"], ["bgColor", "#FFFFFF"]]);
			}
		}
	}
	//dynamic table set style.
	this.parentObjEx.fillProperties(this.elementTabEx, [["width", "100%"], ["height", "100%"], ["border", 0], ["cellPadding", 4], ["cellSpacing", 1], ["align", "center"], ["bgColor", "#E1E1E1"]]);
	
	//first-column merge deal with.
	var templateDate = this.elementTabEx.cells(0);
	var rowSpanCou = 1;
	var deleteCells = 0;	//dynamic dec of table's cells.
	for(var i = 0; i < this.constNestRows - 1; ){
		var itemDate = this.elementTabEx.cells(++i*this.constNestCells - deleteCells);
		if((templateDate.innerText == itemDate.innerText) || (itemDate.innerText == "") || (itemDate.innerHTML == "&nbsp;")){
			rowSpanCou ++;
			itemDate.removeNode(true);
			deleteCells ++;
		}
		else{
			templateDate.rowSpan = rowSpanCou;
			templateDate = this.elementTabEx.cells(i*this.constNestCells - deleteCells);
			rowSpanCou = 1;
		}
	}
	//make sure deal with
	templateDate.rowSpan = rowSpanCou;
};

//init CalendarTabEx instance data
CalendarTabEx.prototype.initInstanceData = function(){
	// for obtain enable view date point that originate.
	if(typeof(this.parentObjEx.pricePerDateLs) == "object" && this.parentObjEx.pricePerDateLs.constructor == Array &&
			this.parentObjEx.pricePerDateLs.length > 0){
		var hResult = this.getTriggerPriceDate([this.parentObjEx.nowServerDate, this.parentObjEx.pricePerDateLs[0]]);
		if(typeof(hResult) == "boolean"){
			this.flagOriginal = hResult;
			// this month first one day.
			this.startDisplayPoint = new Date(this.parentObjEx.pricePerDateLs[0].year, this.parentObjEx.pricePerDateLs[0].month - 1, 1);
		}
		else	this.startDisplayPoint = hResult;	// thus, this date is nowServerDate
	}
	else{
		this.flagHasPrice = false;
		// this month first one day.
		this.startDisplayPoint = new Date(this.parentObjEx.nowServerDate.year, this.parentObjEx.nowServerDate.month - 1, 1);
	}
	// for obtain enable view date point that termination.
	this.endDisplayPoint = this.getTailPriceDate(this.startDisplayPoint, this.flagOriginal);
	
	// product all CalendarTdEx of CalendarCtl.pricePerDateLs
	this.downwardTrEx = new CalendarTrEx(this);
	this.downwardTrEx.initAssociateDate();
};

// tool function for CalendarTabEx
CalendarTabEx.prototype.getTriggerPriceDate = function(param2JsonLs){
	var nowDate = new Date(param2JsonLs[0].year, param2JsonLs[0].month - 1, param2JsonLs[0].date);
	var valuationDate =new Date(param2JsonLs[1].year, param2JsonLs[1].month - 1, param2JsonLs[1].date);
	if(valuationDate <= nowDate)	return	valuationDate;	// in other words, nowDate has price.
	else{
		var dayVal = nowDate.getDay();
		// the original page isn't useableness price
		if((valuationDate - nowDate)/(24*60*60*1000) > (41 - dayVal)){
			return false;	// for this case, this's mean that view the month of valuationDate.
		}
		else
			return nowDate;
	}
};

CalendarTabEx.prototype.getTailPriceDate = function(paramDate, paramFlag){
	//note: paramDate is this.startDisplayPoint and paramFlag is this.flagOriginal.
	var dayVal = paramDate.getDay();
	if(paramFlag)	return new Date(paramDate.getTime() + (41 - dayVal)*(24*60*60*1000));
	else
		for(var i = 1; i < 31; i ++){
			if(paramDate.getMonth() != new Date(paramDate.getTime() + i*(24*60*60*1000)).getMonth()){
				return new Date(paramDate.getTime() + (i - 1)*(24*60*60*1000));	// this month last one day.
			}
		}
};

//init out frame
CalendarCtl.prototype.initOutframe = function(){
	//draw blank table with 27 cells.
	for(var i = 0; i < this.constRows; i ++){
		var eleTr = this.frameTable.insertRow();
		for(var j = 0; j < this.constCells; j ++){
			var eleTd = eleTr.insertCell();
			with(eleTd){
				innerHTML = "&nbsp;";
				bgColor = "#FFFFFF";
				align = "center";
			}
		}
	}
	//fill fix data in layout outer.
	//first thing that merge cell
	this.mergeRowCell(this.frameTable.cells(10), 2, 8);
	this.fillClass(this.frameTable.cells(10), [["padding", 0]]);
	this.frameTable.cells(10).setAttribute("id", this.DyDataTab);	// this is only a reference, for dynamic operation.
	
	this.frameTable.cells(9).setAttribute("id", this.upClickEle);
	this.frameTable.cells(11).setAttribute("id", this.downClickEle);
	
	this.fillProperties(this.frameTable, [["width", 600], ["border", 0], ["cellPadding", 2], ["cellSpacing", 1], ["align", "center"], ["bgColor", "#E1E1E1"]]);
	for(var i = 0; i < this.weekLs.length; i ++){
		this.fillProperties(this.frameTable.cells(i + 2), [["width", 60], ["align", "center"], ["bgColor", "#FFFFFF"], ["innerText", this.weekLs[i]]]);
	}
	this.fillClass(this.frameTable.cells(2), ["green"]);
	this.fillClass(this.frameTable.cells(8), ["green"]);
	//secondly thing that set size
	this.fillProperties(this.frameTable.cells(0), [["width", 24]]);
	this.fillProperties(this.frameTable.cells(1), [["width", 56]]);
	this.fillProperties(this.frameTable.rows(0), [["height", 30]]);
};

// write CalendarCtl in document of this position that invoke this method.
CalendarCtl.prototype.writeActiveX = function(){
	this.initOutframe();
	this.downwardTabEx = new CalendarTabEx(this);
	this.downwardTabEx.initInstanceData();
	document.write(this.frameTable.outerHTML);
	//page date initialization.
	this.DyDataTab = document.getElementById(this.DyDataTab);
	this.upClickEle = document.getElementById(this.upClickEle);
	this.downClickEle = document.getElementById(this.downClickEle);
	var pageTabEx = this.downwardTabEx;
	var pageUpEx = this.upClickEle;
	var pageDownEx = this.downClickEle;

	//binding event for up or down turning.
	this.upClickEle.onclick = function(){
		if((curIndex = -- pageTabEx.downwardTrEx.turningIndex) > 0){
			pageUpEx.innerHTML = "<img src='images/up.jpg' width='10' height='8' style='cursor:hand'>";
			pageDownEx.innerHTML = "<img src='images/down.jpg' width='10' height='8' style='cursor:hand'>";			
		}else if(curIndex == 0){
			pageUpEx.innerHTML = "<img src='images/up_gray.jpg' width='10' height='8'>";
			pageDownEx.innerHTML = "<img src='images/down.jpg' width='10' height='8' style='cursor:hand'>";
		}else{
			pageTabEx.downwardTrEx.turningIndex ++;	
			return true;
		}
		pageTabEx.writeActiveX();
	};
	this.downClickEle.onclick = function(){
		if((curIndex = ++ pageTabEx.downwardTrEx.turningIndex) < pageTabEx.downwardTrEx.turningMaximum){
			pageDownEx.innerHTML = "<img src='images/down.jpg' width='10' height='8' style='cursor:hand'>";
			pageUpEx.innerHTML = "<img src='images/up.jpg' width='10' height='8' style='cursor:hand'>";
		}else if(curIndex == pageTabEx.downwardTrEx.turningMaximum){
			pageDownEx.innerHTML = "<img src='images/down_gray.jpg' width='10' height='8'>";
			pageUpEx.innerHTML = "<img src='images/up.jpg' width='10' height='8' style='cursor:hand'>";
		}else{
			pageTabEx.downwardTrEx.turningIndex --;		
			return true;
		}
		pageTabEx.writeActiveX();
	};
	//page index of initialization.
	this.downwardTabEx.writeActiveX();
	this.DyDataTab.innerHTML = "";
	this.upClickEle.innerHTML = "<img src='images/up_gray.jpg' width='10' height='8'>";
	if(this.downwardTabEx.downwardTrEx.turningMaximum)
		this.downClickEle.innerHTML = "<img src='images/down.jpg' width='10' height='8' style='cursor:hand'>";
	else
		this.downClickEle.innerHTML = "<img src='images/down_gray.jpg' width='10' height='8'>";
	//fill data.
	this.DyDataTab.appendChild(this.downwardTabEx.elementTabEx);
};

//tool function for CalendarCtl
CalendarCtl.prototype.fillProperties = function(targetEle, arrayLs){
	if(typeof(targetEle) == "object" && typeof(arrayLs) == "object" && arrayLs.constructor == Array){
		for(var i = 0; i < arrayLs.length; i ++){
			targetEle.setAttribute(arrayLs[i][0], arrayLs[i][1]);
		}
	}
};

CalendarCtl.prototype.fillClass = function(targetEle, arrayLs){
	if(typeof(targetEle) == "object" && typeof(arrayLs) == "object" && arrayLs.constructor == Array){
		for(var i = 0; i < arrayLs.length; i ++){
			if(i == 0 && typeof(arrayLs[0]) == "string")
				targetEle.className = arrayLs[0];
			else{
				targetEle.style.setAttribute(arrayLs[i][0], arrayLs[i][1]);
			}
		}
	}
};

CalendarCtl.prototype.mergeRowCell = function(targetEle, rowCount, cellCount){
	// merge row and cell prototype case.
	with(targetEle){
		colSpan = cellCount;
		rowSpan = rowCount;
	}
	//FDFL: first merge last cell
	var parTrEle = targetEle.parentNode;
	var preTdPos = targetEle.pcellIndex;
	for(var r = 0; r < rowCount; r ++){
		if(r == 0){
			for(var c = 0; c < cellCount - 1; c ++)
				targetEle.nextSibling.removeNode(true);
		}
		else{
			parTrEle = parTrEle.nextSibling;
			var preTdEle = parTrEle.cells(preTdPos);
			for(var c = 0; c < cellCount - 1; c ++)
				preTdEle.nextSibling.removeNode(true);
			preTdEle.removeNode(true);
		}
	}
};
