// General Date Picker. It has two views, Year-Month and Year-Month-Day
// 
// Terry He				Jan 26 2007		1.0		Updated
// Terry He				Jan 25 2007		0.9		Updated
// Terry He				Jan 23 2007		0.1		Created
//
// Main Functions.
//		IsDisplayed()					Return true if the date picker is displayed, otherwise, return false.
//		SetDisplay(b)					if b is true, display this date picker, otherwise, hide date picker.
//		SetDisplayStyle(b)				if b is ture, display year month and day, otherwise display year and month
//		SetTargetField(o);				Set the input box control that associate with DatePicker.
//		SetInputFormat(sFormat);		Set the input date format. Valid formats: YYYY-MM-DD, MM/DD/YYYY, DD/MM/YYYY, MM/YYYY, YYYY, MM, DD.
//		SetOutputFormat(sFormat);		Set the output date format. Valid formats: YYYY-MM-DD, MM/DD/YYYY, DD/MM/YYYY, MM/YYYY, YYYY, MM, DD.
//		SetPosition(x,y);				Set absolution position of DatePicker. if x, y are not set, date picker automatically shows up below the target date control.
//		SetDate(sDate)					Set the date of date picker displayed first. it should be like 'yyyy-mm-dd';
//
// Example:
//		var oDatePicker = new HDDatePicker(document,id);
// 
//		var oinput=document.getElementById(datefield_id);
//		oDatePicker.SetTargetField(oinput);
//		oDatePicker.SetFullDateFormat(true);
//		oDatePicker.SetInputFormat("MM/DD/YYYY");
//		oDatePicker.SetDate("01/25/2007");
//		oDatePicker.SetOutputformat("MM/DD/YYYY");
//		oDatePicker.SetDate(oinput.value);
//		oDatePicker.SetPosition();
//		oDatePicker.SetDisplay(true);
//  Or
//		var oinput=document.getElementById(datefield_id);
//		oDatePicker.SetTargetField(oinput);
//		oDatePicker.SetFullDateFormat(false);
//		oDatePicker.SetInputFormat("MM/YYYY");
//		oDatePicker.SetDate("01/2007");
//		oDatePicker.SetOutputformat("MM/YYYY");
//		oDatePicker.SetDate(oinput.value);
//		oDatePicker.SetPosition();
//		oDatePicker.SetDisplay(true);


HDDatePickerError={
					InvalidType:		[100,"Invalid control type."],
					InvalidNumber:		[101,"Invalid number"],
					YearOutofRange:		[200,"Please set valid year between 1940 and 2050."],
					MonthOutofRange:	[201,"Please set valid month between 1 and 12."],
					DayOutofRange:		[202,"Please set valid day for that month."],
					WrongInputFormat:	[203,"Please set Invalid input date format."],
					WrongOutputFormat:	[204,"Please set Invalid output date format."]
					};

function HDDatePickerEventHandler(oDatePicker){

	// start of private functions
	function getEventObj(e){
		if(e==null) return null;
		if(e.stopPropagation) e.stopPropagation();
		else e.cancelBubble=true;
		return e.target?e.target:e.srcElement;
	};
	// end of private functions

	// start of public functions
	this.fnChangeYearMonth=function(e){
		var type=e.type.toLowerCase();
		var o=oDatePicker;

		if(type=="click"||type=="dblclick"){
			var oe = getEventObj(e);
			if(oe.id.indexOf(">>")>=0)
				o.Year=(type=="click")?parseInt(o.Year)+1:parseInt(o.Year)+9;
			else if(oe.id.indexOf("<<")>=0)
				o.Year=(type=="click")?parseInt(o.Year)-1:parseInt(o.Year)-9;
			else if(oe.id.indexOf(">")>=0){
				if(parseInt(o.Month)==11) o.Year=parseInt(o.Year)+1;
				o.Month=(parseInt(o.Month)+1)%12;
			}
			else if(oe.id.indexOf("<")>=0){
				if(parseInt(o.Month)==0) o.Year=parseInt(o.Year)-1;
				o.Month=(parseInt(o.Month)+12-1)%12;
			}

			if(o.Year>2050) o.Year=1940+(o.Year-2050);
			else if(o.Year<1940) o.Year=2050-(1940-o.Year);

			o.FillCalendar();
		}
	};

	this.fnMonthSelected=function(e){
		var o=oDatePicker;
		var oe = getEventObj(e);
		o.Day=parseInt(oe.innerHTML);

		var year=""+o.Year;
		var month=(parseInt(o.Month)<9?"0":"")+(parseInt(o.Month)+1);

		if(o.TargetCtrl!=null){
			if(o.OutputFormat=="YYYY-MM-DD")
				o.TargetCtrl.value=year+"-"+month+"-01";
			else if(o.OutputFormat=="MM/DD/YYYY")
				o.TargetCtrl.value=month+"/01/"+year;
			else if(o.OutputFormat=="MM/YYYY")
				o.TargetCtrl.value=month+"/"+year;
			else if(o.OutputFormat=="YYYY")
				o.TargetCtrl.value=year;
			else if(o.OutputFormat=="MM")
				o.TargetCtrl.value=month;
			else if(o.OutputFormat=="DD")
				o.TargetCtrl.value="01";
		}
		else{
		}

		o.SetDisplay(false);
	};

	this.fnDaySelected=function(e){
		var o=oDatePicker;
		var oe = getEventObj(e);
		o.Day=parseInt(oe.innerHTML);

		var year=""+o.Year;
		var month=(parseInt(o.Month)<9?"0":"")+(parseInt(o.Month)+1);
		var day=(parseInt(o.Day)<10?"0":"")+o.Day;

		if(o.TargetCtrl!=null){
			if(o.OutputFormat=="YYYY-MM-DD")
				o.TargetCtrl.value=year+"-"+month+"-"+day;
			else if(o.OutputFormat=="MM/DD/YYYY")
				o.TargetCtrl.value=month+"/"+day+"/"+year;
			else if(o.OutputFormat=="MM/YYYY")
				o.TargetCtrl.value=month+"/"+year;
			else if(o.OutputFormat=="YYYY")
				o.TargetCtrl.value=year;
			else if(o.OutputFormat=="MM")
				o.TargetCtrl.value=month;
			else if(o.OutputFormat=="DD")
				o.TargetCtrl.value=day;
		}
		else{
		}

		o.SetDisplay(false);
	};

	this.fnChangePosition=function(e){
debugger;
	}
	this.fnSetToday=function(e){
		var o=oDatePicker;
		var date=new Date();
		o.Year=date.getFullYear();
		o.Month=date.getMonth();
		o.Day=date.getDate();
		o.FillCalendar();
	};

	this.fnClose=function(e){
		var o=oDatePicker;
		if(o.IsDisplayed())
			o.SetDisplay(false);
	};
	// end of public functions
};

function HDDatePicker(doc,id){
	// start of public properties
	this.doc=doc;
	this.CalendarType="MM/DD/YYYY";
	this.id="DatePickerCtrl"+id;
	this.TargetCtrl = null;
	this.InputFormat = "MM/YYYY";
	this.OutputFormat = "MM/YYYY";

	var date=new Date();
	this.Year=date.getFullYear();
	this.Month=date.getMonth();
	this.Day=date.getDate();
	this.dtDate=new Date();

	this.bPopError=false;

	//this.arDayHeader = new Array('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa');
	//this.arMonth = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
	this.arDays = new Array(31,28,31,30,31,30,31,31,30,31,30,31);

	this.arInputFormat = new Array("YYYY-MM-DD", "MM/DD/YYYY", "DD/MM/YYYY", "MM/YYYY", "YYYY", "MM", "DD");
	this.arOutputFormat = new Array("YYYY-MM-DD", "MM/DD/YYYY", "DD/MM/YYYY", "MM/YYYY", "YYYY", "MM", "DD");
	// end of public properties

	// start of private functions
	function addEvent(o,evt,fn,useCapture){
		return o.addEventListener ? o.addEventListener(evt, fn, useCapture) : o.attachEvent("on"+evt, fn);
	};

	function removeEvent(o,evt,fn,useCapture){
		return o.removeEventListener ? o.removeEventListener(evt, fn, useCapture) : o.detachEvent("on"+evt, fn);
	};
	// end of private functions

	// create event handle 
	this.EventHandler = new HDDatePickerEventHandler(this);

	// start of public functions
	this.IsDisplayed=function(){
		var $d=this.doc;
		var o=$d.getElementById(this.id);
		return (o.style.display=="");
	};

	this.SetDisplay=function(b){
		var $d=this.doc;
		var o=$d.getElementById(this.id);
		o.style.display=(b?"":"none");
	};

	this.SetDate=function(str){
		try{
			if(str=="") str=null;

			if(this.InputFormat=="YYYY-MM-DD"){
				var ar=str.split("-");
				this.dtDate.setYear(ar[0]);
				this.dtDate.setMonth(ar[1].ToInt32()-1);
				this.dtDate.setDate(ar[2]);
			}
			else if(this.InputFormat=="MM/DD/YYYY"){
				var ar=str.split("/");
				this.dtDate.setYear(ar[2]);
				this.dtDate.setMonth(ar[0].ToInt32()-1);
				this.dtDate.setDate(ar[1]);
			}
			else if(this.InputFormat=="MM/YYYY"){
				var ar=str.split("/");
				this.dtDate.setYear(ar[1]);
				this.dtDate.setMonth(ar[0].ToInt32()-1);
			}
			else if(this.InputFormat=="YYYY"){
				var ar=str.split("/");
				this.dtDate.setYear(ar[0]);
			}
			else if(this.InputFormat=="MM"){
				var ar=str.split("/");
				this.dtDate.setMonth(ar[0].ToInt32()-1);
			}
			else if(this.InputFormat=="DD"){
				var ar=str.split("/");
				this.dtDate.setDate(ar[0]);
			}
			
			if(isNaN(this.dtDate))
				this.dtDate= new Date();
		}
		catch(e){
			this.dtDate= new Date();
		}
		
		this.Year=this.dtDate.getFullYear();
		this.Month=this.dtDate.getMonth();
		this.Day=this.dtDate.getDate();

		this.FillCalendar();
	}

	this.GetTargetField=function(){
		return this.TargetCtrl;
	};

	this.SetTargetField=function(o){
		this.TargetCtrl=o;
	};

	this.SetOutputFormat=function(sFormat){
		try{
			for(var i=0;i<this.arOutputFormat.length;i++){
				if(this.arOutputFormat[i]==sFormat.toUpperCase()){
					this.OutputFormat=sFormat.toUpperCase();
					return ;
				}
			}
			throw HDDatePickerError.WrongOutputFormat;
		}
		catch(e){
			alert(e.description?e.description:e[1]);
		}
	};

	this.SetInputFormat=function(sFormat){
		try{
			for(var i=0;i<this.arInputFormat.length;i++){
				if(this.arInputFormat[i]==sFormat.toUpperCase()){
					this.InputFormat=sFormat.toUpperCase();
					return ;
				}
			}
			throw HDDatePickerError.WrongInputFormat;
		}
		catch(e){
			alert(e.description?e.description:e[1]);
		}
	};

	this.SetFullDateMode=function(b){
		this.CalendarType=(b?"MM/DD/YYYY":"MM/YYYY");
	}

	this.SetPosition=function(x,y){
		var odiv=this.doc.getElementById(this.id);
		if(x!=null&&y!=null){
			odiv.style.top=y+"px";
			odiv.style.left=x+"px";
		}
		else
		{
			if (this.TargetCtrl != null)
			{
				var x=this.TargetCtrl.offsetLeft;
				var y=this.TargetCtrl.offsetTop+this.TargetCtrl.offsetHeight;
				// deal with elements inside tables and such
				var parent=this.TargetCtrl;
				while (parent.offsetParent) {
					parent=parent.offsetParent;
					x+=parent.offsetLeft;
					y+=parent.offsetTop ;
				}
				odiv.style.top=y+"px";
				odiv.style.left=x+"px";
			}
		}
	};

	this.FillCalendar=function(){
		var $d=this.doc;

		// set titlel prompt
		var o=$d.getElementById(this.id+"TitlePromptTD");
		addEvent(o,"click",this.EventHandler.fnSetToday,true);
		o.innerHTML=(this.CalendarType=="MM/YYYY" ? CALENDAR_ThisMonth.toUpperCase() : CALENDAR_Today.toUpperCase());
		o.width=(this.CalendarType=="MM/YYYY"?60:15);

		// fill year and month
		var o=$d.getElementById(this.id+"CalendarTitleTD");
		//o.innerHTML=this.arMonth[this.Month]+"&nbsp;"+this.Year;
		o.innerHTML=arMonth[this.Month]+"&nbsp;"+this.Year;

		if(this.CalendarType=="MM/YYYY"){
			o.className="DatePickderTitleSel";
			addEvent(o,"click",this.EventHandler.fnMonthSelected,true);
			var tr=$d.getElementById(this.id+"DatePickderDayHeaderTR");
			tr.style.display="none";
			for(var j=0;j<6;j++){
				var tr=$d.getElementById(this.id+"CalendarDayTR_"+j);
				tr.style.display="none";
			}
		}
		else{
			o.className="DatePickderTitle";
			removeEvent(o,"click",this.EventHandler.fnMonthSelected,true);
			var tr=$d.getElementById(this.id+"DatePickderDayHeaderTR");
			tr.style.display="";

			// fill days
			var days=this.arDays[this.Month];
			if(this.Month==1&&this.Year%4==0)
				days+=1;
			// calculate days.
			var d=new Date();
			d.setFullYear(this.Year);
			d.setMonth(this.Month);
			d.setDate(1);

			var predays=this.arDays[(this.Month+12-1)%12];
			var start=-d.getDay();
			var loop = (days-start)/7;

			for(var j=0;j<6;j++){
				var tr=$d.getElementById(this.id+"CalendarDayTR_"+j);
				tr.style.display=(j>=loop?"none":"");
				for(var i=0;i<7;i++,start++){
					var td=$d.getElementById(this.id+"_CalendarDayTD"+(j*7+i));
					removeEvent(td,"click",this.EventHandler.fnDaySelected,true);
					var d=new Date();
					if(start%days+1==d.getDate()&&this.Month==d.getMonth()&&this.Year==d.getFullYear())
					{
						td.className="DatePickderDayButtonToday";
						addEvent(td,"click",this.EventHandler.fnDaySelected,true);
						td.title=CALENDAR_Today;
					}
					else if(start%days+1==this.dtDate.getDate()&&this.Month==this.dtDate.getMonth()&&this.Year==this.dtDate.getFullYear()){
						td.className="DatePickderDayButtonSel";
						addEvent(td,"click",this.EventHandler.fnDaySelected,true);
						td.title="Day selected";
					}
					else{
						if(start<0||start>=days){
							td.className="DatePickderDayPane";
						}
						else{
							td.className="DatePickderDayButton";
							addEvent(td,"click",this.EventHandler.fnDaySelected,true);
						}
						td.title="";
					}
					td.innerHTML=(start<0?predays+start+1:start%days+1);
				}
			}
		}
	};

	this.PopulateDays=function(){
		var $d=this.doc;
		var tbl=$d.createElement("table");
		tbl.cellpadding=tbl.cellspacing=2;
		tbl.border=0;
		var tbody=$d.createElement("tbody");
		tbl.appendChild(tbody);
		var tr=$d.createElement("tr");
		tr.id=this.id+"DatePickderDayHeaderTR";
		tbody.appendChild(tr);

		for(var i=0;i<7;i++){	
			td=$d.createElement("td");
			td.className="DatePickderDayHeader";
			td.align="center";
			td.valign="bottom";
			//td.innerHTML=this.arDayHeader[i];
			td.innerHTML=arDayHeader[i];
			tr.appendChild(td);
		}

		for(var j=0;j<6;j++){
			tr=$d.createElement("tr");
			tr.id=this.id+"CalendarDayTR_"+j;
			tr.style.display="none";
			if(this.CalendarType=="MM/YYYY")
				tr.className="DatePickderDayButton";
			tbody.appendChild(tr);

			for(var i=0;i<7;i++){
				var td=$d.createElement("td");
				td.id=this.id+"_CalendarDayTD"+(j*7+i);
				td.align="right";
				tr.appendChild(td);
				td.innerHTML="";
			}
		}

		return tbl;
	};

	this.PopulateTitle=function(id){
		var $d=this.doc;
		var tbl=$d.createElement("table");
		var tbody=$d.createElement("tbody");
		tbl.appendChild(tbody);
		var tr=$d.createElement("tr");
		tbody.appendChild(tr);
		var td=$d.createElement("td");
		td.id=id;
		td.width=105;
		td.align="center";
		tr.appendChild(td);
		return tbl;
	};

	this.PopulateNavigation=function(id,txt){
		var $d=this.doc;
		var tbl=$d.createElement("table");
		tbl.className="DatePickderNavButton";
		tbl.id=id;
		if(id=="<<"||id==">>"){
			//addEvent(tbl,"dblclick",this.EventHandler.fnChangeYearMonth,true);
			addEvent(tbl,"click",this.EventHandler.fnChangeYearMonth,true);
		}
		else if(id=="<"||id==">"){
			//addEvent(tbl,"dblclick",this.EventHandler.fnChangeYearMonth,true);
			addEvent(tbl,"click",this.EventHandler.fnChangeYearMonth,true);
		}
		var tbody=$d.createElement("tbody");
		tbl.appendChild(tbody);
		var tr=$d.createElement("tr");
		tbody.appendChild(tr);
		var td=$d.createElement("td");
		td.id="Text_"+id;
		td.align="center";
		tr.appendChild(td);
		td.innerHTML=txt;
		return tbl;
	};

	this.PopulateYearMonth=function(){
		var $d=this.doc;
		var tbl=$d.createElement("table");
		tbl.cellpadding=tbl.cellspacing=tbl.border=0;
		tbl.border=0;
		var tbody=$d.createElement("tbody");
		tbl.appendChild(tbody);
		var tr=$d.createElement("tr");
		tbody.appendChild(tr);
		var td=$d.createElement("td");
		tr.appendChild(td);
		td.appendChild(this.PopulateNavigation("<<","&lt;&lt;"));
		td=$d.createElement("td");
		tr.appendChild(td);
		td.appendChild(this.PopulateNavigation("<","&lt;"));
		td=$d.createElement("td");
		tr.appendChild(td);
		td.appendChild(this.PopulateTitle(this.id+"CalendarTitleTD"));
		td=$d.createElement("td");
		tr.appendChild(td);
		td.appendChild(this.PopulateNavigation(">","&gt;"));
		td=$d.createElement("td");
		tr.appendChild(td);
		td.appendChild(this.PopulateNavigation(">>","&gt;&gt;"));
		return tbl;
	}

	this.PopulateHeader=function(){
		var $d=this.doc;
		var tbl=$d.createElement("table");
		tbl.width="100%";
		var tbody=$d.createElement("tbody");
		tbl.appendChild(tbody);
		var tr=$d.createElement("tr");
		tbody.appendChild(tr);
		var td=$d.createElement("td");
		td.id=this.id+"TitlePromptTD";
		td.align="left";
		td.className="HeaderPrompt";
		tr.appendChild(td);

		td=$d.createElement("td");
		td.align="right";
		tr.appendChild(td);
		img=$d.createElement("img");
		img.border=0;
		img.src="/_images/icons/Icons_Gen_Del.gif";
		addEvent(img,"click",this.EventHandler.fnClose,true);
		td.appendChild(img);

		return tbl;
	};

	this.InitDatePicker=function(){
		var $d=this.doc;
		// create date object
		var div=$d.createElement("div");
		div.id=this.id;
		div.onselectstart=OnDatePickerSelectStart;
		div.className="DatePickerCtrl";
		div.style.cssText="position:absolute;width:205px;height:175px;";
		$d.body.appendChild(div);
		var tbl=$d.createElement("table");
		tbl.cellpadding=tbl.cellspacing=tbl.border=0;
		tbl.className="DatePickerTBL";
		div.appendChild(tbl);
		var tbody=$d.createElement("tbody");
		tbl.appendChild(tbody);
		// Draw Date Picker title
		var tr=$d.createElement("tr");
		addEvent(tr,"drop",this.EventHandler.fnChangePosition,true);
		tr.className="DatePickerHeader";
		tbody.appendChild(tr);
		var td=$d.createElement("td");
		tr.appendChild(td);
		td.appendChild(this.PopulateHeader());
		// Populate Year and Month
		tr=$d.createElement("tr");
		tbody.appendChild(tr);
		var td=$d.createElement("td");
		td.align="center";
		td.colspan=2;
		tr.appendChild(td);
		td.appendChild(this.PopulateYearMonth());
		// Populate Days
		tr=$d.createElement("tr");
		tbody.appendChild(tr);
		td=$d.createElement("td");
		tr.appendChild(td);
		td.appendChild(this.PopulateDays());

		if(this.IsDisplayed())
			this.FillCalendar();

		this.SetDisplay(false);
	};
	// end of public functions
}
