/**
 * Global variables are optional:
 * 		web_language (string, default is "en", maybe in {"vn","en"})
 *		web_limit_mindate (date, default is null)
 *		web_limit_maxdate (date, default is null)
 *		web_current_date  (date, default is Date() == today in client)
 */
//web_limit_mindate = new Date(1970,1,1);
//web_limit_maxdate = new Date(2100,1,1);
(function($) { // Localise the $ function
window.DateInput = function DateInput(el, opts) {
  if (typeof(opts) != "object") opts = {};
  $.extend(this, DateInput.DEFAULT_OPTS, opts);
  this.input = $(el);
  this.bindMethodsToObj("show", "hide", "hideIfClickOutside", "selectDate", "prevMonth", "nextMonth");
  this.build();
  this.selectDate();
  this.hide();
};
if (web_language=='vn'){
DateInput.DEFAULT_OPTS = {
  month_names: ["Th&#225;ng 1&nbsp;-&nbsp;", "Th&#225;ng 2&nbsp;-&nbsp;", "Th&#225;ng 3&nbsp;-&nbsp;", "Th&#225;ng 4&nbsp;-&nbsp;", "Th&#225;ng 5&nbsp;-&nbsp;", "Th&#225;ng 6&nbsp;-&nbsp;", "Th&#225;ng 7&nbsp;-&nbsp;", "Th&#225;ng 8&nbsp;-&nbsp;", "Th&#225;ng 9&nbsp;-&nbsp;", "Th&#225;ng 10&nbsp;-&nbsp;", "Th&#225;ng 11&nbsp;-&nbsp;", "Th&#225;ng 12&nbsp;-&nbsp;"],
  short_month_names: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
  short_day_names: ["CN", "Hai", "Ba", "T&#432;", "N&#259;m", "S&#225;u", "B&#7843;y"],
  start_of_week: 1
};
}else{
	DateInput.DEFAULT_OPTS = {
  month_names: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
  short_month_names: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
  short_day_names: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
  start_of_week: 1
};	
}
DateInput.prototype = {
  build: function() {
    this.monthNameSpan = $('<span class="month_name"></span>');
    this.monthNav = $('<p style="border-bottom: 1px solid #FFFFFF; background-color:#006699; color:#FFFFFF; margin:0px; text-align:center; padding:4px;"></p>').append(
      $('<a href="#" style="color:#FFFFFF; font-weight:bold">&laquo;</a>').click(this.prevMonth),
      " &nbsp; ", this.monthNameSpan, " &nbsp; ",
      $('<a href="#" style="color:#FFFFFF; font-weight:bold">&raquo;</a>').click(this.nextMonth)
    );
    var tableShell = "<table style='background-color:#FFFFFF; border-left: 2px solid #006699; border-bottom: 2px solid #006699; border-right: 2px solid #006699; border-collapse:collapse;' cellpadding='2px' cellspacing='0px'><thead><tr style='background-color:#006699; color:#FFFFFF;'>";
	$(this.adjustDays(this.short_day_names)).each(function() {
		if (this==DateInput.DEFAULT_OPTS.short_day_names[0] || this==DateInput.DEFAULT_OPTS.short_day_names[6])
			tableShell += "<th style='color:#ff7733;font-weight:normal; border: 1px solid #FFFFFF; width:25px;'>" + this + "</th>";
		else
			tableShell += "<th style='font-weight:normal; border: 1px solid #FFFFFF; width:25px;'>" + this + "</th>";
    });
    tableShell += "</tr></thead><tbody></tbody></table>";
    this.dateSelector = this.rootLayers = $('<div class="calendar"></div>')
      .css({ display: "none", position: "absolute", zIndex: 100 })
      .append(this.monthNav, tableShell)
      .appendTo(document.body);
    if ($.browser.msie && $.browser.version < 7) {
      this.ieframe = $('<iframe class="date_selector_ieframe" frameborder="0" src="#"></iframe>')
        .css({ position: "absolute", display: "none", zIndex: 99 })
        .insertBefore(this.dateSelector);
      this.rootLayers = this.rootLayers.add(this.ieframe);
    };
    this.tbody = $("tbody", this.dateSelector);
    this.input.change(this.bindToObj(function() { this.selectDate(); }));
  },
  selectMonth: function(date) {
    this.currentMonth = date;
    var rangeStart = this.rangeStart(date), rangeEnd = this.rangeEnd(date);
    var numDays = this.daysBetween(rangeStart, rangeEnd);
    //window.status = 'Debug selectMonth(): '+web_limit_mindate;
    var dayCells = "";
    for (var i = 0; i <= numDays; i++) {
      var currentDay = new Date(rangeStart.getFullYear(), rangeStart.getMonth(), rangeStart.getDate() + i);
      var dayStyle   = this.isHoliday(currentDay)?'style="color:#ff7733;"':'';
      if (this.isFirstDayOfWeek(currentDay)) dayCells += "<tr class='days'>";
      dayCells += '<td align="right" date="' + this.dateToString(currentDay) + '"';
      if (currentDay.getMonth() == date.getMonth()
      	&& (typeof(web_limit_mindate)=='undefined' || web_limit_mindate<=currentDay)
      	&& (typeof(web_limit_maxdate)=='undefined' || web_limit_maxdate>=currentDay)) {
        dayCells += ' ><a href="#" '+dayStyle+'>' + currentDay.getDate() + '</a></td>';
      } else {
        dayCells += ' style="color:#BBBBBB;">' + currentDay.getDate() + '</td>';
      };
      if (this.isLastDayOfWeek(currentDay)) dayCells += "</tr>";
    };
    this.monthNameSpan.empty().append(this.monthName(date) + " " + date.getFullYear());

    this.tbody.empty().append(dayCells);
    $("a", this.tbody).click(this.bindToObj(function(event) {
      this.selectDate(this.stringToDate($(event.target).parent().attr("date")));
      this.hide();
      return false;
    }));
    
    $("td[date=" + this.dateToString((typeof(web_current_date)!='object'?new Date():new Date(web_current_date))) + "]", this.tbody).addClass("currentDate");
  },
  isHoliday: function(date){
  	var i = date.getDay();
  	return (i==0 || i==6);
  },
  selectDate: function(date) {
    if (typeof(date) == "undefined") {
      date = this.stringToDate(this.input.val());
    }
    else {
        var impact_id = $('#'+this.input.attr('id') + '_next').val();
        if(impact_id != 'undefined') {
        	date.setDate(date.getDate()+1);
	  		$('#' + impact_id).val(this.dateToString(date));
	  		$('#' + impact_id).unbind();
	  		$('#' + impact_id).date_input();
	  		date.setDate(date.getDate()-1);
        }    	
    };
    if (date) {
      this.selectedDate = date;
      this.selectMonth(date);
      $('td[date=' + this.dateToString(date) + ']', this.tbody).addClass("selectedDate");
      this.input.val(this.dateToString(date));
    } else {
      this.selectMonth((typeof(web_current_date)!='object'?new Date():new Date(web_current_date)));
    };
  },
  show: function() {
    this.setPosition();
    this.rootLayers.css("display", "block");
    this.input.unbind("focus", this.show);
    $([window, document.body]).click(this.hideIfClickOutside);
    $([window, document.body]).keydown(this.hideIfLostFocus);
	jquery_active_date_input = this;
  },
  hide: function() {
    this.rootLayers.css("display", "none");
    $([window, document.body]).unbind("click", this.hideIfClickOutside);
    this.input.focus(this.show);
  },
  hideIfLostFocus: function(event){
	  if (event.keyCode==9 || event.keyCode==13 || event.keyCode==27)
	  {
		jquery_active_date_input.rootLayers.css("display", "none");
		$([window, document.body]).unbind("click", jquery_active_date_input.hideIfClickOutside);
		$([window, document.body]).unbind("keydown", jquery_active_date_input.hideIfLostFocus);
		jquery_active_date_input.input.focus(jquery_active_date_input.show);
	  }
  },
  hideIfClickOutside: function(event) {
    if (event.target != this.input[0] && !this.insideSelector(event)) {
      this.hide();
    };
  },
  stringToDate: function(string) {
    var matches;
    if (web_language=="vn")
    	var pattern = /^(\d{1,2})\/(\d{1,2})\/(\d{4,4})$/;
    else
    	var pattern = /^(\d{4,4})-(\d{1,2})-(\d{1,2})$/;
    
    if (matches = string.match(pattern)) {
		var s='';
		if (web_language=="vn")
			s= new Date(matches[3], this.shortMonthNum(matches[2]), matches[1]);
		else
			s= new Date(matches[1], this.shortMonthNum(matches[2]), matches[3]);
		//window.status = 'Debug: '+s;
		if (isNaN(s)) return null;
		return s;
   } else {
      return null;
    };
  },
  dateToString: function(date) {
	var s='';
    if (web_language=="vn")
	    s= date.getDate() + "/" + this.short_month_names[date.getMonth()] + "/" + date.getFullYear();
	else
	    s= date.getFullYear() + "-" + this.short_month_names[date.getMonth()] + "-" + date.getDate(); 
	return s;
  },
  setPosition: function() {
    var offset = this.input.offset();
    this.rootLayers.css({
      top: offset.top + this.input.outerHeight(),
      left: offset.left
    });
    if (this.ieframe) {
      this.ieframe.css({
        width: this.dateSelector.outerWidth(),
        height: this.dateSelector.outerHeight()
      });
    };
  },
  moveMonthBy: function(amount) {
    if (this.currentMonth.getDate()>28) this.currentMonth.setDate(1);
  	this.selectMonth(new Date(this.currentMonth.setMonth(this.currentMonth.getMonth() + amount)));
  },
  /*prevMonth_able: function(){
  	var date = null;
	if (typeof(this.currentMonth) == "undefined") {
		date = this.stringToDate(this.input.val());
	}
	if (!date) {
		date = (typeof(web_current_date)!='object'?new Date():web_current_date);
	}
	date.setDate(0);
	if (typeof(web_limit_mindate)!='undefined'&&web_limit_mindate>date) return false;
	return true;
  },
  nextMonth_able: function(){
  	var date = null;
	if (typeof(this.currentMonth) == "undefined") {
		date = this.stringToDate(this.input.val());
	}
	if (!date) {
		date = (typeof(web_current_date)!='object'?new Date():web_current_date);
	}
	date.setMonth(date.getMonth()+1);
	date.setDate(1);
	if (typeof(web_limit_maxdate)!='undefined'&&web_limit_maxdate<date) return false;
	return true;
  },*/
  prevMonth: function() {
  	var prev = new Date(this.currentMonth);
  	prev.setDate(0);
  	//window.status = 'Current={'+this.currentMonth+'}; Prev={'+prev+'}; Min={'+web_limit_mindate+'}';
  	if (typeof(web_limit_mindate)!='undefined'&&web_limit_mindate>prev) return false;
    this.moveMonthBy(-1);
    return false;
  },
  nextMonth: function() {
  	var next = new Date(this.currentMonth);
  	next.setDate(1);
  	next.setMonth(next.getMonth()+1);
  	//window.status = 'Current={'+this.currentMonth+'}; Next={'+next+'}; Max={'+web_limit_maxdate+'}';
  	if (typeof(web_limit_maxdate)!='undefined'&&web_limit_maxdate<next) return false;
    this.moveMonthBy(1);
    return false;
  },
  monthName: function(date) {
    return this.month_names[date.getMonth()];
  },
  insideSelector: function(event) {
    var offset = this.dateSelector.offset();
    offset.right = offset.left + this.dateSelector.outerWidth();
    offset.bottom = offset.top + this.dateSelector.outerHeight();
    return event.pageY < offset.bottom &&
           event.pageY > offset.top &&
           event.pageX < offset.right &&
           event.pageX > offset.left;
  },
  bindToObj: function(fn) {
    var self = this;
    return function() { return fn.apply(self, arguments) };
  },
  bindMethodsToObj: function() {
    for (var i = 0; i < arguments.length; i++) {
      this[arguments[i]] = this.bindToObj(this[arguments[i]]);
    };
  },
  indexFor: function(array, value) {
    for (var i = 0; i < array.length; i++) {
      if (value == array[i]) return i;
    };
  },
  monthNum: function(month_name) {
    return this.indexFor(this.month_names, month_name);
  },
  shortMonthNum: function(month_name) {
    return this.indexFor(this.short_month_names, month_name);
  },
  shortDayNum: function(day_name) {
    return this.indexFor(this.short_day_names, day_name);
  },
  daysBetween: function(start, end) {
    start = Date.UTC(start.getFullYear(), start.getMonth(), start.getDate());
    end = Date.UTC(end.getFullYear(), end.getMonth(), end.getDate());
    return (end - start) / 86400000;
  },
  changeDayTo: function(to, date, direction) {
    var difference = direction * (Math.abs(date.getDay() - to - (direction * 7)) % 7);
    return new Date(date.getFullYear(), date.getMonth(), date.getDate() + difference);
  },
  rangeStart: function(date) {
    return this.changeDayTo(this.start_of_week, new Date(date.getFullYear(), date.getMonth()), -1);
  },
  rangeEnd: function(date) {
    return this.changeDayTo((this.start_of_week - 1) % 7, new Date(date.getFullYear(), date.getMonth() + 1, 0), 1);
  },
  isFirstDayOfWeek: function(date) {
    return date.getDay() == this.start_of_week;
  },
  isLastDayOfWeek: function(date) {
    return date.getDay() == (this.start_of_week - 1) % 7;
  },
  adjustDays: function(days) {
    var newDays = [];
    for (var i = 0; i < days.length; i++) {
      newDays[i] = days[(i + this.start_of_week) % 7];
    };
    return newDays;
  }
};
$.fn.date_input = function(opts) {
  return this.each(function() { new DateInput(this, opts); });
};
$.date_input = { initialize: function(opts) {
  $("input.date_input").date_input(opts);
} };
})(jQuery); // End localisation of the $ function

