/**
 * Copyright (C) 2009 eXo Platform SAS.
 * 
 * This is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 * 
 * This software is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this software; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
 * site: http://www.fsf.org.
 */

(function($, base, common, msg) {
	eXo.webui.UICalendar = {
	  calendarId : "UICalendarControl",
	  dateField : null,
	  datePattern : null,
	  value : null,
	  currentDate : null, // Datetime value base of selectedDate for displaying
	                      // calendar below
	  // if selectedDate is invalid, currentDate deals with system time;
	  selectedDate : null, // Datetime value of input date&time field
	  months : null,
	
	  firstDayOfWeek : 1,// Indecates what the first day of the week is; e.g.,
	                      // SUNDAY (1) in the U.S, MONDAY (2) in France, TUESDAY
	                      // (3), etc
	  weekdays : null,
	  
	  hideCalendarHandler : null,
	
	  init : function(field, isDisplayTime, datePattern, value, monthNames) {
	    this.isDisplayTime = isDisplayTime;
	
	    if (this.dateField) {
	      this.dateField.parentNode.style.position = '';
	    }
	    this.dateField = field;
	    this.datePattern = datePattern;
	    this.value = value;
	
	    this.months = new Array();
	    this.months = monthNames.split(',');
	    this.months.pop();
	
	    var weekdays = msg.getMessage("weekdays");
	    if (weekdays != null && typeof (weekdays) == "object") {
	      this.weekdays = weekdays;
	    }
	
	    if (!document.getElementById(this.calendarId))
	      this.create();
	    this.show();
	
	    // fix bug for IE 6
	    var cld = document.getElementById(this.calendarId);
	    if (base.Browser.isIE6()) {
	      var blockClnd = document.getElementById('BlockCalendar');
	      var iframe = document.getElementById(this.calendarId + 'IFrame');
	      iframe.style.height = blockClnd.offsetHeight + "px";
	    }
	    field.parentNode.insertBefore(cld, field);
	  },

      triggerChangeEvent: function() {
        if(this.dateField) {
          $(this.dateField).change();
        }
      },
	
	  create : function() {
	    var clndr = document.createElement("div");
	    clndr.id = this.calendarId;	   
			clndr.style.position = "absolute";
			clndr.style.zIndex = "99";
	    if (base.Browser.isIE6()) {
	      clndr.innerHTML = "<div class='calendarComponent' ><iframe id='"
	          + this.calendarId
	          + "IFrame' frameBorder='0' style='position:absolute;height:100%;' scrolling='no'></iframe><div style='position:absolute;'></div></div>";
	    } else {
	      clndr.innerHTML = "<div class='calendarComponent' ><div style='position: absolute; width: 100%;'></div></div>";
	    }
	    document.body.appendChild(clndr);
	  },
	
	  show : function() {
	    //document.onclick = function() {eXo.webui.UICalendar.hide()};
		if(!this.hideCalendarHandler) {
		  this.hideCalendarHandler = function() {eXo.webui.UICalendar.hide();};
		}
		if(document.addEventListener) {
		  document.addEventListener("click", this.hideCalendarHandler, false);
		} else if(document.attachEvent) {
		  document.attachEvent("onclick", this.hideCalendarHandler);
		} else {
		  document.onclick = function() {eXo.webui.UICalendar.hide()};
		}
	    var re = /^(\d{1,2}\/\d{1,2}\/\d{1,4})\s*(\s+\d{1,2}:\d{1,2}:\d{1,2})?$/i;
	    this.selectedDate = new Date();
	
	    // if (re.test(this.dateField.value)) {
	    // var dateParts = this.dateField.value.split(" ") ;
	    // var arr = dateParts[0].split("/") ;
	    // this.selectedDate.setMonth(parseInt(arr[0],10) - 1) ;
	    // this.selectedDate.setDate(parseInt(arr[1],10)) ;
	    // this.selectedDate.setFullYear(parseInt(arr[2],10)) ;
	    // if (dateParts.length > 1 && dateParts[dateParts.length - 1] != "") {
	    // arr = dateParts[dateParts.length - 1].split(":") ;
	    // this.selectedDate.setHours(arr[0], 10) ;
	    // this.selectedDate.setMinutes(arr[1], 10) ;
	    // this.selectedDate.setSeconds(arr[2], 10) ;
	    // }
	    // }
	    if (this.dateField.value != '') {
	      // TODO: tamnd - set selected date to calendar
	      var dateFieldValue = this.dateField.value;
	
	      var dateIndex = this.datePattern.indexOf("dd");
	      var dateValue = parseInt(dateFieldValue.substring(dateIndex,
	          dateIndex + 2), 10);
	
	      var monthIndex = this.datePattern.indexOf("MM");
	      var monthValue = parseInt(dateFieldValue.substring(monthIndex,
	          monthIndex + 2) - 1, 10);
	
	      var yearIndex = this.datePattern.indexOf("yyyy");
	      var yearValue = parseInt(dateFieldValue.substring(yearIndex,
	          yearIndex + 4), 10);
	
	      var hourIndex = this.datePattern.indexOf("HH");
	      var hoursValue = parseInt(dateFieldValue.substring(hourIndex,
	          hourIndex + 2), 10);
	
	      var minuteIndex = this.datePattern.indexOf("mm");
	      var minutesValue = parseInt(dateFieldValue.substring(minuteIndex,
	          minuteIndex + 2), 10);
	
	      var secondIndex = this.datePattern.indexOf("ss");
	      var secondValue = parseInt(dateFieldValue.substring(secondIndex,
	          secondIndex + 2), 10);
	
	      if (isNaN(secondValue)) {
	        secondValue = "00";
	      }
	      if (isNaN(minutesValue)) {
	        minutesValue = "00";
	      }
	      if (isNaN(hoursValue)) {
	        hoursValue = "00";
	      }
	
	      var testDate = "MM/dd/yyyy HH:mm:ss";
	      testDate = testDate.replace("dd", dateValue);
	      testDate = testDate.replace("MM", monthValue + 1);
	      testDate = testDate.replace("yyyy", yearValue);
	      testDate = testDate.replace("HH", hoursValue);
	      testDate = testDate.replace("mm", minutesValue);
	      testDate = testDate.replace("ss", secondValue);
	
	      if (re.test(testDate)) {
	    	this.selectedDate.setFullYear(yearValue);
	    	this.selectedDate.setMonth(monthValue);
	    	this.selectedDate.setDate(dateValue);
	        this.selectedDate.setHours(hoursValue);
	        this.selectedDate.setMinutes(minutesValue);
	        this.selectedDate.setSeconds(secondValue);
	      }
	
	    }
	    this.currentDate = new Date(this.selectedDate.valueOf());
	    var clndr = document.getElementById(this.calendarId);
	    clndr.firstChild.lastChild.innerHTML = this.renderCalendar();
	    // var x = 0 ;
	    $(clndr).css('top', $(this.dateField).position().top);
	    var y = this.dateField.offsetHeight;
	    var beforeShow = $(window).height();
	    if (eXo.core.I18n.isLT())
	    	$(clndr.firstChild).css('left', 0);
	    else
	    	$(clndr.firstChild).css('right', 0);
	    $(clndr.firstChild).css( {
	    	'display' : 'block',
	    	//left = x + "px" ;
	    	'top' : y + "px"
	    });
	    var posCal = $(this.dateField).offset().top - y;
	    var heightCal = document.getElementById('BlockCalendar');
	    var afterShow = posCal + heightCal.offsetHeight;
	    if (afterShow > beforeShow) {
	      clndr.firstChild.style.top = -heightCal.offsetHeight + 'px';
	    }
	
	    // eXo.webui.UICalendar.initDragDrop();
	
	    var primary = $(this.dateField).closest("#UIECMSearch");
	    if (primary.length && base.Browser.isFF()) {
	      var calendar = clndr.firstChild;
	      calendar.style.top = "0px";
	      calendar.style.left = this.dateField.offsetLeft
	          - this.dateField.offsetWidth - 32 + "px";
	    }
		$("#BlockCalendar a[rel='tooltip']").tooltip();
	  },
	
	  onTabOut : function(event) {
	    var keyCode = event.keyCode;
	
	    // identify the tab key
	    if (keyCode == 9) {
	      eXo.webui.UICalendar.hide();
	    }
	  },
	
	  hide : function() {
	    if (this.dateField) {
	      document.getElementById(this.calendarId).firstChild.style.display = 'none';
	      // this.dateField.parentNode.style.position = '' ;
	      this.dateField.blur();
	      this.dateField = null;
	    }
	    if(document.removeEventListener) {
		  document.removeEventListener("click", this.hideCalendarHandler, false);
		} else if(document.detachEvent) {
		  document.detachEvent("onclick", this.hideCalendarHandler);
		} else {
		  document.onclick = null;
		}
	    // document.onmousedown = null;
	  },
	
	  /* TODO: Move HTML code to a javascript template file (.jstmpl) */
	  renderCalendar : function() {
	    var dayOfMonth = 1;
	    var validDay = 0;
	    var startDayOfWeek = this.getDayOfWeek(this.currentDate.getFullYear(),
	        this.currentDate.getMonth() + 1, dayOfMonth);
	    var daysInMonth = this.getDaysInMonth(this.currentDate.getFullYear(),
	        this.currentDate.getMonth());
	    var clazz = null;
	    var table = '<div id="BlockCalendar" class="uiCalendarComponent uiBox" onclick="event.cancelBubble = true">';
		table += '<div onmousedown="event.cancelBubble = true" style="cursor: default">';
	    table += '<h5 class="title clearfix">';
		table += '<a data-placement="right" rel="tooltip" onclick="eXo.webui.UICalendar.changeMonth(-1);" class="actionIcon pull-left" data-original-title="'+msg.getMessage("PreviousMonth")+'"><i class="uiIconMiniArrowLeft uiIconLightGray"></i></a>';
	    table += '<span>'+ this.months[this.currentDate.getMonth()] + ', '+ this.currentDate.getFullYear() + '</span>';
		table += '<a data-placement="right" rel="tooltip" onclick="eXo.webui.UICalendar.changeMonth(1);" class="actionIcon pull-right" data-original-title="'+msg.getMessage("NextMonth")+'"><i class="uiIconMiniArrowRight uiIconLightGray"></i></a>';
	    table += '</h5>';

	    table += '<table class="weekList">';
	    table += '  <tr>';
	    
		if (this.weekdays == null) {
	    	this.weekdays = new Array("S", "M", "T", "W", "T", "F", "S");
	    }
		for ( var i = 0; i < 7; i++) {
	      if (i == (8 - this.firstDayOfWeek) % 7) {
	        table += ' <td><font color="red">'
	            + this.weekdays[(i + this.firstDayOfWeek - 1) % 7] + '</font></td>';
	      } else {
	        table += ' <td>' + this.weekdays[(i + this.firstDayOfWeek - 1) % 7]
	            + '</td>';
	      }
	    }
	    
	    table += '  </tr>';
	    table += '</table>';
	    table += '<hr>';

		var _pyear, _pmonth, _pday, _nyear, _nmonth, _nday, _weekend;
		var _today = new Date();
		var tableRow='';
		if(startDayOfWeek==0) startDayOfWeek = 7;
		_pyear = (this.currentDate.getMonth() == 0) ? this.currentDate.getFullYear() - 1 : this.currentDate.getFullYear();
		_pmonth = (this.currentDate.getMonth() == 0) ? 11 : this.currentDate.getMonth() - 1;
		_pday = this.getDaysInMonth(_pyear, _pmonth) - ((startDayOfWeek + ((8 - this.firstDayOfWeek) % 7)) % 7) + 1;
		
		_nmonth = (this.currentDate.getMonth() == 11) ? 0 : this.currentDate.getMonth() + 1;
		_nyear = (this.currentDate.getMonth() == 11) ? this.currentDate.getFullYear() + 1 : this.currentDate.getFullYear();
		_nday = 1;
		
		table += '<table cellspacing="0" cellpadding="0" id="" class="weekDays">';
	    for ( var week = 0; week < 6; week++) {
		  tableRow += '<tr {{week'+week+'}}>';
	      for ( var dayOfWeek = 0; dayOfWeek <= 6; dayOfWeek++) {
	        if (week == 0
	            && dayOfWeek == (startDayOfWeek + ((8 - this.firstDayOfWeek) % 7)) % 7) {
	          validDay = 1;
	        } else if (validDay == 1 && dayOfMonth > daysInMonth) {
	          validDay = 0;
	        }
	        if (validDay) {
	          if (dayOfMonth == this.selectedDate.getDate()
	              && this.currentDate.getFullYear() == this.selectedDate
	                  .getFullYear()
	              && this.currentDate.getMonth() == this.selectedDate.getMonth()) {
	            clazz = 'selected';
	          } else {
	            clazz = '';
	          }
			  if(_today.getDate() == dayOfMonth
	              && this.currentDate.getFullYear() == _today.getFullYear()
	              && this.currentDate.getMonth() == _today.getMonth()) {
				clazz = 'highLight today';
				tableRow = tableRow.replace('{{week'+week+'}}','class="currentWeek"');
			  }
	          tableRow = tableRow + '<td><a class="' + clazz
	              + '" href="#SelectDate" onclick="eXo.webui.UICalendar.setDate('
	              + this.currentDate.getFullYear() + ','
	              + (this.currentDate.getMonth() + 1) + ',' + dayOfMonth + ')">'
	              + dayOfMonth + '</a></td>';
	          dayOfMonth++;
			  _weekend = week;
	        } else if(validDay == 0 && week == 0) {
	          tableRow = tableRow + '<td><a href="#SelectDate" class="otherMonth" onclick="eXo.webui.UICalendar.setDate('
	              + _pyear + ','
	              + (_pmonth + 1) + ',' + _pday + ')">'
	              + _pday + '</a></td>';
				_pday++;
	        } else if(validDay == 0 && week != 0 && _weekend==week){
				tableRow = tableRow + '<td><a href="#SelectDate" class="otherMonth" onclick="eXo.webui.UICalendar.setDate('
	              + _nyear + ','
	              + (_nmonth + 1) + ',' + _nday + ')">'
	              + _nday + '</a></td>';
				_nday++;
			}
	      }
	      tableRow += "</tr>";
		  tableRow = tableRow.replace('{{week'+week+'}}','');
	    }
	    table += tableRow + '</table>';
	    
		if (this.isDisplayTime) {
	      table += ' <div class="calendarTimeInput">';
	      table += '   <span><input type="text" class="InputTime" maxlength="2" value="'
	          + ((this.currentDate.getHours()) > 9 ? this.currentDate.getHours()
	              : "0" + this.currentDate.getHours())
	          + '" onkeyup="eXo.webui.UICalendar.setHour(this)" onfocus="this.parentNode.className=\'focus\'" onblur="this.parentNode.className=\'\'">'
			  + ':'
			  + '<input type="text" class="InputTime" maxlength="2" value="'
	          + ((this.currentDate.getMinutes()) > 9 ? this.currentDate
	              .getMinutes() : "0" + this.currentDate.getMinutes())
	          + '" onkeyup = "eXo.webui.UICalendar.setMinus(this)" onfocus="this.parentNode.className=\'focus\'" onblur="this.parentNode.className=\'\'"></span>';
	      table += ' </div>';
	    }

	    table += '</div>';
		table += '</div>';
	    return table;
	  },
	
	  changeMonth : function(change) {
	    this.currentDate.setDate(1);
	    this.currentDate.setMonth(this.currentDate.getMonth() + change);
	    var clndr = document.getElementById(this.calendarId);
	    clndr.firstChild.lastChild.innerHTML = this.renderCalendar();
	
	    // eXo.webui.UICalendar.initDragDrop();
	  },
	
	  initDragDrop : function() {
	    var drag = $("#BlockCalendar");
	    var component = drag.closest(".calendarComponent");    
	    var calendar = drag.children(".UICalendar").first();
	    var innerWidth = drag[0].offsetWidth;
	
	    common.DragDrop.init(drag[0], component[0]);
	    component[0].onDragStart = function() {
	      if (base.Browser.isIE7())
	        drag.height(calendar[0].offsetHeight);
	      drag.width(innerWidth);
	    }
	  },
	
	  changeYear : function(change) {
	    this.currentDate.setFullYear(this.currentDate.getFullYear() + change);
	    this.currentDay = 0;
	    var clndr = document.getElementById(this.calendarId);
	    clndr.firstChild.lastChild.innerHTML = this.renderCalendar();
		$("#BlockCalendar a[rel='tooltip']").tooltip();
	    // eXo.webui.UICalendar.initDragDrop();
	  },
	
	  setDate : function(year, month, day) {
	    if (this.dateField) {
	      if (month < 10)
	        month = "0" + month;
	      if (day < 10)
	        day = "0" + day;
	      var dateString = this.datePattern;
	      dateString = dateString.replace("dd", day);
	      dateString = dateString.replace("MM", month);
	      dateString = dateString.replace("yyyy", year);
	
	      this.currentHours = this.currentDate.getHours();
	      this.currentMinutes = this.currentDate.getMinutes();
	      this.currentSeconds = this.currentDate.getSeconds();
	      if (this.isDisplayTime) {
	        if (typeof (this.currentHours) != "string")
	          hour = this.currentHours.toString();
	        if (typeof (this.currentMinutes) != "string")
	          minute = this.currentMinutes.toString();
	        if (typeof (this.currentSeconds) != "year")
	          second = this.currentSeconds.toString();
	
	        while (hour.length < 2) {
	          hour = "0" + hour;
	        }
	        while (minute.length < 2) {
	          minute = "0" + minute;
	        }
	        while (second.length < 2) {
	          second = "0" + second;
	        }
	
	        dateString = dateString.replace("HH", hour);
	        dateString = dateString.replace("mm", minute);
	        dateString = dateString.replace("ss", second);
	      }
	      this.dateField.value = dateString;
          this.triggerChangeEvent();
	      this.hide();
	    }
	    return;
	  },
	
	  getDateTimeString : function() {
	    if (!this.currentDate)
	      return this.datePattern;
	    var year = "" + this.currentDate.getFullYear();
	    var month = "" + (this.currentDate.getMonth() + 1);
	    if (month.length < 2)
	      month = "0" + month;
	    var day = "" + this.currentDate.getDate();
	    if (day.length < 2)
	      day = "0" + day;
	    var hour = "" + this.currentDate.getHours();
	    if (hour.length < 2)
	      hour = "0" + hour;
	    var minute = "" + this.currentDate.getMinutes();
	    if (minute.length < 2)
	      minute = "0" + minute;
	    var second = "" + this.currentDate.getSeconds();
	    if (second.length < 2)
	      second = "0" + second;
	
	    var dateString = $.trim(this.datePattern);
	    if (!this.isDisplayTime) {
	      var ptStrings = dateString.split(" ");
	      for ( var i = 0; i < ptStrings.length; i++) {
	        if (ptStrings[i].indexOf("yyyy") >= 0) {
	          dateString = ptStrings[i];
	          break;
	        }
	      }
	    }
	
	    dateString = dateString.replace("dd", day);
	    dateString = dateString.replace("MM", month);
	    dateString = dateString.replace("yyyy", year);
	    if (this.isDisplayTime) {
	      dateString = dateString.replace("HH", hour);
	      dateString = dateString.replace("mm", minute);
	      dateString = dateString.replace("ss", second);
	    }
	
	    return dateString;
	  },
	
	  setSeconds : function(object) {
	    if (this.dateField) {
	      var seconds = object.value;
	      if (isNaN(seconds))
	        return;
	      if (seconds >= 60) {
	        object.value = seconds.substring(0, 1);
	        return;
	      }
	      if (seconds.length < 2)
	        seconds = "0" + seconds;
	      this.currentDate.setSeconds(seconds);
	      this.currentDay = this.currentDate.getDate();
	      this.currentMonth = this.currentDate.getMonth() + 1;
	      this.currentYear = this.currentDate.getFullYear();
	      this.dateField.value = this.getDateTimeString();
          this.triggerChangeEvent();
	    }
	    return;
	  },
	
	  setMinus : function(object) {
	    if (this.dateField) {
	      var minus = object.value;
	      if (isNaN(minus))
	        return;
	      if (minus >= 60) {
	        object.value = minus.substring(0, 1);
	        return;
	      }
	      if (minus.length < 2)
	        minus = "0" + minus;
	      this.currentDate.setMinutes(minus);
	      this.currentDay = this.currentDate.getDate();
	      this.currentMonth = this.currentDate.getMonth() + 1;
	      this.currentYear = this.currentDate.getFullYear();
	      this.dateField.value = this.getDateTimeString();
          this.triggerChangeEvent();
	    }
	    return;
	  },
	
	  setHour : function(object) {
	    if (this.dateField) {
	      var hour = object.value;
	      if (isNaN(hour))
	        return;
	      if (hour >= 24) {
	        object.value = hour.substring(0, 1);
	        return;
	      }
	      if (hour.length < 2)
	        hour = "0" + hour;
	      this.currentDate.setHours(hour);
	      this.currentDay = this.currentDate.getDate();
	      this.currentMonth = this.currentDate.getMonth() + 1;
	      this.currentYear = this.currentDate.getFullYear();
	      this.dateField.value = this.getDateTimeString();
          this.triggerChangeEvent();
	    }
	    return;
	  },
	
	  clearDate : function() {
	    this.dateField.value = '';
        this.triggerChangeEvent();
	    this.hide();
	  },
	
	  getDayOfWeek : function(year, month, day) {
	    var date = new Date(year, month - 1, day);
	    return date.getDay();
	  },
	
	  getDaysInMonth : function(year, month) {
	    return [ 31, ((!(year % 4) && ((year % 100) || !(year % 400))) ? 29 : 28),
	        31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ][month];
	  },
	
	  getFirstDayOfWeek : function() {
	    return this.firstDayOfWeek;
	  },
	
	  setFirstDayOfWeek : function(dayOfWeek) {
	    this.firstDayOfWeek = dayOfWeek;
	  }
	};
	
	return eXo.webui.UICalendar;
})($, base, common, msg);
