/**
 * Copyright 2006 Expedia, Inc. All rights reserved.
 * EXPEDIA PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 * Version 1.0
 * Library includes basic javascript functions as well as calendar controls for the site.
 */

//This is ported from YUI for now, but needs to be removed on refactor
var Class = {
	create: function() {
		return function() {
			this.initialize.apply(this, arguments);
		}
	}
}

Calendar = Class.create();
Calendar.prototype = 
{
    initialize: function (calendarConfig) 
	{
		this.m_calendarConfig = calendarConfig;
	
		this.rM = new Array(12);
		this.rM[0]=this.rM[2]=this.rM[4]=this.rM[6]=this.rM[7]=this.rM[9]=this.rM[11]=31;
		this.rM[3]=this.rM[5]=this.rM[8]=this.rM[10]=30;
		this.rM[1]=28;
	},
	getDateFormat: function ()
	{
		return this.m_calendarConfig.getDateFormat();
	},
	getDateSeparator: function ()
	{
		return this.m_calendarConfig.getDateSeparator();
	},
	getDowStart: function ()
	{
		return this.m_calendarConfig.getStartOfWeek();
	},
	getDateFromString: function (t)
	{
		if(!t.length) return null;
		t=t.replace(/\s+/g,"");
		if(t.match(/[^-|\d|\.|\/]/)) return null;
		var rgt=t.split(/-|\.|\//);
		for(var i=0;i<rgt.length;i++) rgt[i]=parseInt(rgt[i],10);
		if(!rgt[1]) return null;
		var m,d,y;
		var fmt=this.getDateFormat();
		if(fmt=="yymmdd")
		{
		if(!rgt[2]) return null;
		m=rgt[1];d=rgt[2];y=rgt[0];
		}
		else
		{
		if(fmt=="mmddyy"){m=rgt[0];d=rgt[1];}
		else{m=rgt[1];d=rgt[0];}//fmt=="ddmmyy"
		if(rgt[2])y=rgt[2];
		else y=this.DefYr(m-1,d);
		}
		m-=1;if(y<100)y+=2000;
		if(y<1601||y>4500||m<0||m>11||d<1||d>this.getMonthCount(m,y))return null;
		return new Date(y,m,d);
	},
	toStringFromComp: function (d,m,y)
	{
		var out="";
		var ds=this.getDateSeparator();
		var fmt=this.getDateFormat();
		if(fmt=="mmddyy")out=m+ds+d+ds+y;
		else if(fmt=="ddmmyy")out=d+ds+m+ds+y;
		else out=y+ds+m+ds+d;
		return out;
	},
	IsLY: function (y) 
	{if(0==y%4&&((y%100!=0)||(y%400==0)))return true;else return false;},
	DefYr: function (m,d)
	{var dt=new Date();var yC=(dt.getYear()<1000)?1900+dt.getYear():dt.getYear();if(m<dt.getMonth()||(m==dt.getMonth()&&d<dt.getDate()))yC++;return yC;},
	getMonthCount: function (m,y)
	{var c=this.rM[m];if((1==m)&&this.IsLY(y))c++;return c;}

};


DateUpdater = Class.create();
DateUpdater.prototype = 
{
	initialize: function (calendar)
	{
		this.calendar = calendar;
	},
	register: function (idFrom, idTo, c)
	{
		var thisThis=this;
		var fn = function () { thisThis.update(idFrom, idTo, c);};
		YAHOO.util.Event.addListener(idFrom, 'blur', fn);
	},
	update: function (idFrom, idTo, c)
	{
		var objFrom = YAHOO.util.Dom.get(idFrom);
		var dt1 = this.calendar.getDateFromString(YAHOO.util.Dom.get(idFrom).value);
		if (dt1)
		{
			dt1 = new Date(dt1.valueOf() + 1000 * 3600 * 24 * c);
			var dt2 = this.calendar.getDateFromString(YAHOO.util.Dom.get(idTo).value);
			if (dt2 && dt2 <= dt1) dt2 = null;
			if (null==dt2)
			{
				var objTo = YAHOO.util.Dom.get(idTo);
				objTo.value = this.calendar.toStringFromComp(dt1.getDate(),dt1.getMonth()+1,dt1.getFullYear());
			}
		}
	}
};

DPDisplay = Class.create();
DPDisplay.prototype = 
{
    initialize: function (id,path) 
	{
		this.id = id;
		this.path = path;
	},
	createFrame: function ()
	{
		//If we can't find anything by this id then go ahead and add it
		if(!this.getContainer())
		{
			var html = '';
			html += '<iframe id="' + this.id + '" name="' + this.id + '" src="' + this.path + '" ';
			html += 'style="display:block;visibility:hidden;position:absolute;width:148px;height:194px;z-index:1000" ';
			html += 'marginheight="0" marginwidth="0" noresize frameborder="0" scrolling="no"></iframe>';
			var el = document.createElement('div');
			el.innerHTML = html;
			document.body.appendChild(el);
		}
	},
	getContainer: function ()
	{
		return YAHOO.util.Dom.get(this.id);
	},
	getFrame: function ()
	{
		return getFrame(this.id);
	},
	show: function (id, idP, dateMin, dateMax)
	{
		hideFrame(this.id);
		this.position(id);
		var thisThis = this;
		g_timeOutFn = function () {	thisThis.getFrame().DoCal(id,idP,dateMin,dateMax); };
		setTimeout("g_timeOutFn()", 1);
	},
	position: function(id)
	{
		var dB=document.body;
		var e = YAHOO.util.Dom.get(id);
		var eL=0;
		var eT=0;

		for(var p=e;p&&p.tagName!='BODY';p=p.offsetParent)
		{
			eL+=p.offsetLeft;
			eT+=p.offsetTop;
		}

		var eH=e.offsetHeight;
		var dH=this.getContainer().style.pixelHeight;
		var sT=dB.scrollTop;

		if(eT-dH>=sT&&eT+eH+dH>dB.clientHeight+sT)
			eT-=dH;
		else
			eT+=eH;

		this.getContainer().style.left=eL+'px';
		this.getContainer().style.top=eT+'px';
	},
	hide: function (id)
	{
		hideFrame(this.id);
	}
};

DPDisplay.typeSingle = new DPDisplay('CalFrame1', '/daily/Shared/common/Calendar/calx2.html');
DPDisplay.typeDouble = new DPDisplay('CalFrame2', '/daily/Shared/common/Calendar/calx2.html');
DPDisplay.useAphrodite = DPDisplay.typeSingle;
DPDisplay.useAphrodite2 = DPDisplay.typeDouble;

DPEntry = Class.create();
DPEntry.prototype = 
{
    initialize: function (id, idPos, floater, dateMin, dateMax, callback) 
	{
		this.id = id;
		this.idPos = idPos;
		this.floater = floater;
		this.dateMin = dateMin;
		this.dateMax = dateMax;
		this.callback = callback;
	},
	show: function ()
	{
		this.floater.show(YAHOO.util.Dom.get(this.id), YAHOO.util.Dom.get(this.idPos), this.dateMin, this.dateMax);
	}
};

DPControl = Class.create();
DPControl.prototype = 
{
    initialize: function (calendar) 
	{
		this.calendar = calendar;
		this.dpentries = new Array();
		this.entryCurrent = null;
		this.tid=0;
	},
	getCalendar: function ()
	{
		return this.calendar;
	},
	getFloat: function ()
	{
		return (this.entryCurrent) ? this.entryCurrent.floater: null;
	},
	getCalFrame: function ()
	{
		return (this.getFloat()) ? this.getFloat().getFrame() : null;
	},
	getCalObject: function ()
	{
		return (this.getFloat()) ? this.getFloat().getContainer() : null;
	},
	register: function (objInp, objPos, floater, dateMin, dateMax, callback)
	{
	    
		this.dpentries[objInp.id] = new DPEntry(objInp.id, objPos.id, floater, dateMin, dateMax, callback);
		
		//TODO: We should optimize this in the future so it does not create the frame on immediate page load
		var fnLoad = function () { floater.createFrame(); };
		YAHOO.util.Event.addListener(window, 'load', fnLoad);		

		var thisThis = this;

		var fnOnBlur = function (evt) { thisThis.blurEvent(evt); };
		YAHOO.util.Event.addListener(objInp, 'blur', fnOnBlur);
		
		var fnOnFocus = function (evt) { thisThis.focusEvent(evt, objInp, objPos); };
		YAHOO.util.Event.addListener(objInp, 'focus', fnOnFocus);

		var fnOnClick = function (evt) { thisThis.clickEvent(evt, objInp, objPos); };
		YAHOO.util.Event.addListener(objInp, 'click', fnOnClick);

	},
	pick: function(objInp)
	{
		
		clearTimeout(this.tid);
		//Don't understand this yet
		if(g_fNoCal){g_fNoCal=false;return;}
		
		if(this.entryCurrent && this.entryCurrent.id == objInp.id)
			return;
		
		var entryNext = this.dpentries[objInp.id];
		//if(this.entryCurrent && this.entryCurrent.floater != entryNext.floater)
		//	this.cancel();
		this.entryCurrent = entryNext;
		
		this.wait(objInp);
	},
	wait: function (obj)
	{
		if(null==this.getCalFrame()||null==this.getCalFrame().g_fCL||false==this.getCalFrame().g_fCL)
		{
			var thisThis = this;
			g_timeOutFn = function () {	thisThis.pick(obj); };
			this.tid=setTimeout("g_timeOutFn()", 200);
		}
		else
		{
			this.show(obj);
		}
	},
	show: function (obj)
	{
		this.entryCurrent.show();
	},
	update: function (obj,d,m,y)
	{
		obj.value = this.calendar.toStringFromComp(d,m,y);
		CalSetFocus(obj);
	},
	cancel: function ()
	{
		clearTimeout(this.tid);
		this.tid=0;
		if(this.entryCurrent)
		{
			this.getFloat().hide();
		}
		this.entryCurrent = null;
	},
	callback: function ()
	{
		if(this.entryCurrent && this.entryCurrent.callback)
			this.entryCurrent.callback;
	},
	blurEvent: function (evt)
	{
		var event = getEventObj(evt);
		stopBubble(event);
	},
	focusEvent: function (evt, objInp, objPos)
	{
		var event = getEventObj(evt);
		objInp.select();
		this.pick(objInp);
	},
	clickEvent: function (evt, objInp, objPos)
	{
		var event = getEventObj(evt);
		stopBubble(event);
		this.pick(objInp);
	}
};


//======================================
//==	BEGIN CLEANUP
//======================================

//TODO: fix click/hide issue
//TODO: make calendars customizable
//TODO: figure out focus issues

var nextFocus;
var g_fNoCal=false;
function getDatePicker() {return g_datepicker;}
function getCalendar() {return g_datepicker.getCalendar();}
function getCalFrame() {return g_datepicker.getCalFrame();}
function getCalObject() {return g_datepicker.getCalObject();}


function CancelCal()
{
	g_datepicker.cancel();
}



function SetNextFocus(e)
{
	nextFocus=e;
	if(nextFocus)
		nextFocus.onfocus=CancelCal;
}

function SetPrevFocus(e){if(e)e.onfocus=CancelCal;}

//function SetKeyPress(obj){if(obj){obj.onkeydown=function(e){var kc;if(window.event){kc=window.event.keyCode;}else if(e){kc=e.which;}if(kc==9){CancelCal();}}}}

//function FGoNextFocus(){if(nextFocus){nextFocus.focus();return true;}return false;}

function EndCalFocus(){g_fNoCal=false;}


if ('undefined' == typeof(exp))
	{
		var exp = new Object();
	}
	if ('undefined' == typeof(expediaNS.core))
	{
		expediaNS.core = new Object();
	}
	if ('undefined' == typeof(expediaNS.core.date))
	{
		expediaNS.core.date = new Object();
	}
	
	expediaNS.core.date.calendarcontrol = function ()
	{
		var date = function ()
		{
			var m_fmt = 'mmddyy';
			var m_sep = '/';
			var m_sow = 0;
			var m_months = ['January','February','March','April','May','June','July','August','September','October','November','December'];
			var m_dayAbbrs = ['S','M','T','W','T','F','S'];
			var m_closeText = 'Close';
		
			var setFormatConfig = function (fmt, sep)
			{
				m_fmt = fmt;
				m_sep = sep;
			};

			var setUnitConfig = function (sow, months, dayAbbrs)
			{
				m_sow = sow;
				m_months = months;
				m_dayAbbrs = dayAbbrs;
			};
		
			var setTextConfig = function (closeText) 
			{
				m_closeText = closeText;
			};
		
			return {
				setFormatConfig: setFormatConfig,
				setUnitConfig: setUnitConfig,
				setTextConfig: setTextConfig,
				getDateFormat: function () {return m_fmt;},
				getDateSeparator: function () {return m_sep;},
				getStartOfWeek: function () {return m_sow;},
				getMonths: function () {return m_months;},
				getDayAbbrs: function () {return m_dayAbbrs;},
				getCloseText: function () {return m_closeText;}
				};
		}
		
		return {Config: new date('ddmmyy', '.', 2)};
	}();




/////////////////////////////////////////////////
////	EXTERNALLY USED
/////////////////////////////////////////////////


function CalSetFocus(e)
{
	if(e)
	{
		g_fNoCal=true;
		e.focus();
		setTimeout("EndCalFocus()", 200);
	}
}
/////////////////////////////////////////////////
////	EXTERNALLY USED
/////////////////////////////////////////////////

	//BEGIN: Javascript for date logic

	
	if(document.documentElement && document.documentElement.offsetHeight)
		document.documentElement.onclick=CancelCal;
	else
		var i;
		//AddClickFn(CancelCal);
	
//======================================
//==	END CLEANUP
//======================================