(function($) {
  //
  // Start Closure
  //
  //global variables
  var yuc = YAHOO.widget.CalendarGroup,
		 yum = YAHOO.widget.DateMath,
		 yud = YAHOO.util.Dom,
		 yue = YAHOO.util.Event;
		 
	var calendarFocus = false;
	var currentField = "";
	var dateFormatPattern = "";
	var currentDateRange;
	
	//Calendar Plugin Definition
  $.fn.calendarWidget= function() {
		 //create a calendar Instance, which will be updated later in Show function
		
		 $('body').prepend("<div id=\"calContainer\"/>");
		 
		var attributes = {
			pages : 2,
			HIDE_BLANK_WEEKS : true,
			LOCALE_WEEKDAYS : "1char",
			close: true
		};
		//get the calContainer for the Form to pass into YUI calendar Object
		var calContainerObject = $('#calContainer').css('position', 'absolute').get(0);		
		//calendar initialization
		var calWidget = new yuc(calContainerObject, attributes);
		
		//before render Event
		calWidget.beforeRenderEvent.subscribe(setDateRange, calWidget, true);
		//render event
		calWidget.renderEvent.subscribe(displayDateRange, calWidget, true);
		//selectEvent
		calWidget.selectEvent.subscribe(selectedDate, calWidget, true);
		//attaching dom events
    	yue.on(calWidget.containerId, 'mouseover', over, calWidget, true);
        yue.on(calWidget.containerId, 'mouseout', out, calWidget, true);
    	$(this).bind('click focus', {cal:calWidget}, show);
    	$(this).bind('blur', {cal:calWidget}, hide);
		
		$(this).bind('change', {cal:calWidget}, hideAndPrePop );
  };
  
	//private functions to plugin
	//event handlers
	function over(type, args, cal) {
        calendarFocus = true;
    };
    function out(type, args, cal) {
        calendarFocus = false;
    };
	//show event handler, we populate/update our calendar in this function
	function show(e) {
   		currentField = this;
   		//configure Calendar
   		var calAttributes = configureCalendarOptions(this);
   		//create Calendar
   		e.data.cal.cfg.setProperty('mindate', calAttributes.mindate);
   		e.data.cal.cfg.setProperty('maxdate', calAttributes.maxdate);
   		e.data.cal.cfg.setProperty('MONTHS_LONG', calAttributes.MONTHS_LONG);
   		e.data.cal.cfg.setProperty('WEEKDAYS_1CHAR', calAttributes.WEEKDAYS_1CHAR);
   		e.data.cal.cfg.setProperty('MY_LABEL_YEAR_POSITION', calAttributes.MY_LABEL_YEAR_POSITION);
   		e.data.cal.cfg.setProperty('MY_LABEL_MONTH_POSITION', calAttributes.MY_LABEL_MONTH_POSITION);
   		e.data.cal.cfg.setProperty('MY_LABEL_YEAR_SUFFIX', calAttributes.MY_LABEL_YEAR_SUFFIX);
		e.data.cal.render();
   		  		
   		var date = $(this).val();
		var container = yud.get(e.data.cal.containerId); 
		var dateObj ;
		var coordinates = getPosition(currentField, container) ;
		// get the form specific section
		var section = "";
		if($(currentField.form).find(':hidden[name=section]').length > 0)
		{
			section = $(currentField.form).find(':hidden[name=section]').val();
		}
		
   		var minDate = calAttributes.mindate;
   		var maxDate = calAttributes.maxdate;

   		if (date) {
			var validDate = true ;
			if(!isDateValid(date,dateFormatPattern) || 
			isDateLessThanDate1(date,formatDate(minDate,dateFormatPattern),dateFormatPattern) || 
			isDateGreaterThanDate1(date,formatDate(maxDate,dateFormatPattern),dateFormatPattern) ){
				validDate = false ;
			}

			if(validDate){
				//If the user enters date in different format, convert to 
				//'mm/dd/yy' in order for the calendar to render properly.
				date = dateInMMDDYYFormat(date,dateFormatPattern) ;
				e.data.cal.cfg.setProperty('selected', date);
				dateObj = new Date(date) ;
			}
			else {
				e.data.cal.cfg.setProperty('selected', '');
				//On travel agents commission search page, the calendar needs to displayed backwards
				if(section == "tacomm"){
					dateObj = new Date(maxDate) ;
				}else{
					dateObj = new Date() ;
				}
			}
			e.data.cal.setMonth(dateObj.getMonth());
			e.data.cal.setYear(dateObj.getFullYear());
       		e.data.cal.render();
   		} 
		else {
       		e.data.cal.cfg.setProperty('selected', '');
			//For travel agents commission search page, the calendar needs to displayed backwards
			if(section == "tacomm"){
				dateObj = new Date(maxDate) ;
			}else{
				dateObj = new Date() ;
			}
			e.data.cal.setMonth(dateObj.getMonth());
			e.data.cal.setYear(dateObj.getFullYear());
       		e.data.cal.render();
   		}
   		
   		yud.setStyle(e.data.cal.containerId, 'display', 'block');
		yud.setX(e.data.cal.containerId, coordinates.x);
		yud.setY(e.data.cal.containerId, coordinates.y);
		
	};
	// if date is added manually, then this function prepopulate the toDate on change event
	function hideAndPrePop(e) {
		var formObj = this.form;
		var section = $(formObj).find(':hidden[name=section]').val();
		if(section !== "emsearch" || section !== "emrfp")
		{
			if (!calendarFocus) {
				$('#'+e.data.cal.containerId).css('display', 'none');
			}
			prePopToDate('',this,true) ;
		}
	};
	// hides the calendar.
	function hide(e) {
		if (!calendarFocus) {
			$('#'+e.data.cal.containerId).css('display', 'none');
		}
	};
	// Calendar selectEvent handler
	function selectedDate(type, args, cal) {
		var calDate = this.getSelectedDates()[0];
		calDate = (calDate.getMonth() + 1) + '/' + calDate.getDate() + '/' + calDate.getFullYear();
		$(currentField).val(formatDate(calDate,dateFormatPattern));
		//If defaultToDateDays is not null ,prepopulate the toDate field based on the from date value
		prePopToDate(calDate,currentField,false) ;

		calendarFocus = false;
		
		if (!calendarFocus) {
			$('#'+this.containerId).css('display', 'none');
		}
		//Events and meeting specific functionality
		// get the form specific section
		var section = "";
		if($(currentField.form).find(':hidden[name=section]').length > 0)
		{
			section = $(currentField.form).find(':hidden[name=section]').val();
		}
		if(section == "emsearch"){
			$(currentField).trigger("emDateSelectEvent");
		}else if(section == "emrfp"){
			$(currentField).trigger("emrfpDateSelectEvent");
		}
	};
	// Calendar beforeRenderEvent handler
	function setDateRange(type, args, cal) {
		var pagedate = this.cfg.getProperty("pagedate");
		
		if (yum.before(pagedate, currentDateRange.from)) {
			this.cfg.setProperty("pagedate", currentDateRange.from);
		}
		if (yum.after(pagedate, currentDateRange.to)) {
			this.cfg.setProperty("pagedate", currentDateRange.to);
		}
		
	};
	// Calendar renderEvent handler
	function displayDateRange(type, args, cal) {
		var leftArrow = $("."+this.Style.CSS_NAV_LEFT, this.oDomContainer);
		var rightArrow = $("."+this.Style.CSS_NAV_RIGHT, this.oDomContainer);

		var pagedate0 = this.pages[0].cfg.getProperty("pagedate");
		var pagedate1 = this.pages[1].cfg.getProperty("pagedate");
		
		if (pagedate0.getMonth() == currentDateRange.from.getMonth() && pagedate0.getFullYear() == currentDateRange.from.getFullYear()) {
			$(leftArrow).css('visibility', 'hidden');
		} else {
			$(leftArrow).css('visibility', 'visible');
		}

		if (pagedate1.getMonth() == currentDateRange.to.getMonth() && pagedate1.getFullYear() == currentDateRange.to.getFullYear()) {
			$(rightArrow).css('visibility', 'hidden');
		} else {
			$(rightArrow).css('visibility', 'visible');
		}
		
		if (pagedate0.getMonth() == currentDateRange.to.getMonth() && pagedate0.getFullYear() == currentDateRange.to.getFullYear()) {
			$(rightArrow).css('visibility', 'hidden');
		}
	};
	//Utility Functions.
	//gets the positions for Calendar Container.
	function getPosition(target, obj) {
		var x = yud.getX(target);
		var y = yud.getY(target);
		
		var containerHeight = obj.offsetHeight;

		var maxXPos = x+330;
		var maxYPos = y + containerHeight;

		var screenWidth = 0 ;
		var screenWidth = yud.getViewportWidth();
		var screenHeight = yud.getViewportHeight();

		var top = (document.documentElement.scrollTop ? document.documentElement.scrollTop :document.body.scrollTop);
		var left = (document.documentElement.scrollLeft ? document.documentElement.scrollLeft :document.body.scrollLeft);
		var viewTop = parseInt(screenHeight + top);
		var viewLeft = parseInt(screenWidth + left);
		var coordinates = new Object();

		if(viewLeft >= maxXPos){
			coordinates.x = x;
		} 
		else {
			coordinates.x = x - 325;
		}

		if ( viewTop >= maxYPos ) {
			coordinates.y = y + 16;
		}
		else {
			coordinates.y = y - (containerHeight - 1);
		}
		return coordinates ;
	};	
	// prepopulates the toDate Field based on fromDate field.	
	function prePopToDate(calDate,currentField,onblurEvent){
		var form = currentField.form;
		var maxDate = $(form).find(':hidden[name=maxDate]').val();
		var populateTodateFromFromDateProperty = $(form).find(':hidden[name=populateTodateFromFromDate]').val();
		var defaultToDateDaysProperty = $(form).find(':hidden[name=defaultToDateDays]').val();
		var toDateElementIndex = $(form).find(':input.calendar-module-fromdate').index(currentField);
		var toDateField = $(form).find(':input.calendar-module-todate').eq(toDateElementIndex);
		if(populateTodateFromFromDateProperty == "true" && $(toDateField).length > 0 &&($(toDateField).get(0) !== currentField))
		{
			if($(toDateField).length > 0)
			{
				var currentToDate = '' ;
				if(onblurEvent){
					calDate = $(currentField).val();
					if(calDate != null && calDate != '' && isDateValid(calDate,dateFormatPattern)){
						var commaDelimitedDate = getCommaDelimitedDate(calDate,dateFormatPattern) ;
						var dateArr = commaDelimitedDate.split(",") ;
						calDate = dateArr[1]+"/"+dateArr[2]+"/"+dateArr[0] ;
					}else{
						calDate = ''; 
					}
				}
				
				if((calDate != null && calDate.length > 0) && 
					isDateLessThanOrEqualToDate1(calDate,maxDate,"mm/dd/yy")){
					//If to date is null,invalid or is less than from date, make todate = fromDate + defaultToDateDays
					
					currentToDate = $(toDateField).val();
					if((currentToDate == null || currentToDate == '' ) || 
						!isDateValid(currentToDate,dateFormatPattern) ||
						!isDateGreaterThanDate1(dateInMMDDYYFormat(currentToDate,dateFormatPattern),calDate,"mm/dd/yy") ){
						
						var toDate = new Date(calDate) ;
						toDate.setDate(toDate.getDate()+parseInt(defaultToDateDaysProperty)) ;
						toDate = (toDate.getMonth() + 1) + '/' + toDate.getDate() + '/' + toDate.getFullYear();
						$(toDateField).val(formatDate(toDate,dateFormatPattern));
					}
				}
				
			}
			
		}
	};
	// Extract calendar options from the form.
	function configureCalendarOptions (currentField){
		//based on current field, construct the calendar config object
		var formObj = currentField.form;
		var minDate = $(formObj).find(':hidden[name=minDate]').val();
		var maxDate = $(formObj).find(':hidden[name=maxDate]').val();
		dateFormatPattern = $(formObj).find(':hidden[name=dateFormatPattern]').val().toLowerCase();
		currentDateRange = {from:new Date(minDate), to:new Date(maxDate)};
		
		var yearMonthDisplay = "";
		var monthPosition = "1";	
		var yearPosition = "2";	
		var yearSuffix = "";
		if($(formObj).find(':hidden[name=yearMonthDisplay]').length > 0)
		{
			yearMonthDisplay = $(formObj).find(':hidden[name=yearMonthDisplay]').val();
			if(yearMonthDisplay == 'Y')
			{
				yearPosition = "1";	
				monthPosition = "2";	
			}
			yearSuffix =  $(formObj).find(':hidden[name=yearSuffix]').val();
		}
		
		var monthNames = "";
		var weekDays = "";
		if($(formObj).find(':hidden[name=monthNames]').length > 0)
		{
			monthNames = $(formObj).find(':hidden[name=monthNames]').val().split(",");
		}
		if($(formObj).find(':hidden[name=weekDays]').length > 0)
		{
			weekDays = $(formObj).find(':hidden[name=weekDays]').val().split(",");
		}
		
		var calAttributes = {
			mindate : minDate,
			maxdate : maxDate,
			MONTHS_LONG : monthNames,
			WEEKDAYS_1CHAR : weekDays,
			MY_LABEL_YEAR_POSITION: yearPosition,
			MY_LABEL_MONTH_POSITION: monthPosition,
			MY_LABEL_YEAR_SUFFIX: yearSuffix
		};
		
		return calAttributes;		
	};
})(jQuery);
