var DAYSOFW = new Array("Di","Lu","Ma","Me","Je","Ve","Sa");
var DAYSOFWK = new Array("Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi");
var MONTHS = new Array("Janvier","F&eacute;vrier","Mars","Avril","Mai","Juin","Juillet","Ao&ucirc;t","Septembre","Octobre","Novembre","D&eacute;cembre");
var SHRTM = new Array('','Jan.','Fev.','Mars','Avril','Mai','Juin','Juil.','Aout','Sept.','Oct.','Nov.','Dec.' );


//----------------------------------------------------------------//
//------------------------Date Utils Objects----------------------//
//----------------------------------------------------------------//
// this way all date fields start from 1
function DateUtilsClass() {
    this.getDay = getDay;
    this.getMonth = getMonth;
    this.getYear = getYear;
    this.setDay = setDay;
    this.setMonth = setMonth;
    this.setYear = setYear;
    this.addYear = addYear;
    this.newDate = newDate;
    this.padZero = padZero;
    this.getDayStr = getDayStr;
    this.getMonthStr = getMonthStr;
    this.getComparInt = getComparInt;
    this.equals = equals;
    this.getDaysInMonth = getDaysInMonth;
    this.clone = clone;

    function getDay(date) {    return date.getDate(); }
    function getMonth(date) { return date.getMonth()+1;    }
    function getYear(date) { return date.getFullYear();    }
    function setDay(date, day) { date.setDate(day); return date; }
    function setMonth(date, month) { date.setMonth(month - 1); return date; }
    function setYear(date, year) { date.setFullYear(year); return date; }
    function addYear(date, yearOffset) { date.setFullYear(date.getFullYear() + yearOffset); return date; }
    function newDate(year, month, day) { return new Date(year, month - 1, day);    }
    function padZero(num) { return ((num <= 9) ? ("0" + num) : num); }
    function getDayStr(date) { return padZero(getDay(date)); }
    function getMonthStr(date) { return padZero(getMonth(date)); }
    function getComparInt(date, useYears) {
        if (useYears == null) useYears = true;
        if (useYears) {
            return parseInt('' + getYear(date) + getMonthStr(date) + getDayStr(date), 10);
        } else {
            return parseInt('' + getMonthStr(date) + getDayStr(date), 10);
        }
    }
    function equals(date1, date2, useYears) {
        return getComparInt(date1, useYears) == getComparInt(date2, useYears);
    }
    function getDaysInMonth(m, y) {
        monthdays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
        if (m != 2) {
            return monthdays[m];
        } else {
            return ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0 ? 29 : 28);
        }
    }
    function clone(date) { var newDate = new Date(); newDate.setTime(date.getTime()); return newDate; }

}
// simulates static methods
var DateUtils = new DateUtilsClass();

// dateListener is a function: argument: sourceCompoundDate
//--------------------------------------------------//
//----------------CompoundDate Object---------------//
//--------------------------------------------------//
function CompoundDate(objName, formName, options) {
    if (formName === null) {
        formName = "form[0]";
    }
    this.today = new Date();
    this.options = Object.extend({
            objectsToHide: [],
            anchorElement: null,
            imgDir: "img",
            fromDate: this.today,
            toDate: DateUtils.newDate(DateUtils.getYear(this.today) + 1, DateUtils.getMonth(this.today), DateUtils.getDay(this.today))
        }, options || {});
    /* Properties */
    this.objName         = objName;
    if(this.year < 2000) this.year += 1900; //for Netscape
    this.yearComboRange = 1; // we only show this and the next year
    this.formName         = formName;
    this.dayObj            = '';
    this.monthObj        = '';
    this.yearObj        = '';
    this.monthNames        = SHRTM;
    this.dateListener   = null;

    /* Public Methods */
    this.setDateListener    = setDateListener;
    this.setToToday            = setToToday;
    this.getDate            = getDate;
    this.setDate            = setDate;
    this.setDateParts        = setDateParts;
    // the getxxx methods all start from 1
    this.getSelYear            = getSelYear;
    this.getSelMonth        = getSelMonth;
    this.getSelDay            = getSelDay;

    this.showCalendar       = showCalendar;
    // called by select boxes
    this.fieldChanged       = fieldChanged;
    // called by the calendar
    this.calendarHidden     = calendarHidden;

    /* Private Methods */
    this._initOptions        = _initOptions;
    this._writeYearOptions     = _writeYearOptions;
    this._writeMonthOptions = _writeMonthOptions;
    this._writeDayOptions     = _writeDayOptions;
    this._updateDayOfWeek    = _updateDayOfWeek;
    this._setVisibility     = _setVisibility;
    this._adjustDaysInMonthFromForm    = _adjustDaysInMonthFromForm;
    this._adjustDaysInMonth    = _adjustDaysInMonth;

    /* Constructor Code */
    this.dayObj = eval("document." + this.formName + ".elements['" + this.objName + ".day']");
    this.monthObj = eval("document." + this.formName + ".elements['" + this.objName + ".month']");
    this.yearObj = eval("document." + this.formName + ".elements['" + this.objName + ".year']");
    this.dayOfWeekObj = document.getElementById(this.objName + ".dayOfWeek");

    this._initOptions();
    this.setToToday();
    this._adjustDaysInMonthFromForm();
    this._updateDayOfWeek();

    // preload images
    var imgUp = new Image(25,25);
    imgUp.src = this.options.imgDir + '/calendar/up.gif';
    var imgDown = new Image(25,25);
    imgDown.src = this.options.imgDir + '/calendar/down.gif';

    //--------------------------public Methods-----------------------//
    function setDateListener(dateListener) {
        this.dateListener = dateListener;
    }
    function calendarHidden() {
        this._setVisibility(true);
        if (typeof(updateFormVisibility) != "undefined") {
            updateFormVisibility();
        }
    }
    function getSelYear() {
        return this.yearObj[this.yearObj.selectedIndex].value;
    }
    function getSelMonth() {
        return this.monthObj[this.monthObj.selectedIndex].value;
    }
    function getSelDay() {
        return this.dayObj[this.dayObj.selectedIndex].value;;
    }
    // Set the date boxes to today's date
    function setToToday() {
        this.setDateParts(DateUtils.getYear(this.today), DateUtils.getMonth(this.today), DateUtils.getDay(this.today));
    }
    function getDate() {
        return DateUtils.newDate(this.getSelYear(), this.getSelMonth(), this.getSelDay());
    }
    function setDate(date) {
        this.setDateParts(DateUtils.getYear(date), DateUtils.getMonth(date), DateUtils.getDay(date));
    }
    /**
    * . Set the date boxes to specific date
    * . called at the init and by the calendar
    * @param integer year
    * @param integer month
    * @param integer day
    */
    function setDateParts( year, month, day ) {
        this._adjustDaysInMonth(month, year); // must be called first
        this.dayObj[day-1].selected = true;
        this.monthObj[month-1].selected = true;
        for(i = 0; i < this.yearObj.length; i++ ) {
            if( this.yearObj[i].value == year )
                this.yearObj[i].selected = true;
        }
        this._updateDayOfWeek();
        if (this.dateListener != null) {
            this.dateListener(this);
        }
    }

    function fieldChanged() {
        this._updateDayOfWeek();
        this._adjustDaysInMonthFromForm();
        if (this.dateListener != null) {
            this.dateListener(this);
        }
    }

    function showCalendar(event) {
        this._setVisibility(false);
        g_Calendar.show(event, this);
    }

    //-----------------------private Methods-----------------------//
    function _updateDayOfWeek(){
        // all parts start from 1
        var date = DateUtils.newDate(this.getSelYear(), this.getSelMonth(), this.getSelDay());
        var dayOfWeek = date.getDay();
        this.dayOfWeekObj.innerHTML = DAYSOFWK[dayOfWeek];
    }
    function _setVisibility(visible) {
        var visibleStr = visible ? "visible" : "hidden";
        for (var i = 0; i < this.options.objectsToHide.length; i++) {
            this.options.objectsToHide[i].style.visibility = visibleStr;
        }
    }

    function _adjustDaysInMonthFromForm() {
        var month = this.monthObj[this.monthObj.selectedIndex].value;
        var year = this.yearObj[this.yearObj.selectedIndex].value;
        this._adjustDaysInMonth(month, year);
    }
    function _adjustDaysInMonth(month, year) {
        var daysForThisSelection = DateUtils.getDaysInMonth(month, year);
        var prevDaysInSelection = this.dayObj.length;

        if (prevDaysInSelection > daysForThisSelection) {
            for (i=0; i<(prevDaysInSelection - daysForThisSelection); i++) {
                this.dayObj.options[this.dayObj.options.length - 1] = null
            }
        }
        if (daysForThisSelection > prevDaysInSelection) {
            var prevLastDay = this.dayObj.options.length;
            for( i = prevLastDay+1; i <= daysForThisSelection; i++ ) {
                var newOption = new Option( i, i );
                var optionsColl = this.dayObj.options;
                optionsColl[optionsColl.length] = newOption;
            }
        }
        if (this.dayObj.selectedIndex < 0)
            this.dayObj.selectedIndex == 0;
    }

    function _initOptions() {
        this._writeYearOptions();
        this._writeMonthOptions();
        this._writeDayOptions();
    }

    function _writeYearOptions() {
        var minYear = DateUtils.getYear(this.options.fromDate);
        var maxYear = DateUtils.getYear(this.options.toDate);
        for( i = minYear; i <= maxYear; i++) {
            var newOption = new Option(i, i);
            var optionsColl = this.yearObj.options;
            optionsColl[optionsColl.length] = newOption;
        }
    }
    function _writeMonthOptions() {
        for( i=1; i <= 12; i++ ) {
            var newOption = new Option( this.monthNames[i], i );
            var optionsColl = this.monthObj.options;
            optionsColl[optionsColl.length] = newOption;
        }
    }
    function _writeDayOptions() {
        for( i=1; i <= 31; i++ ) {
            var newOption = new Option( i, i );
            var optionsColl = this.dayObj.options;
            optionsColl[optionsColl.length] = newOption;
        }
    }
}


//--------------------------------------------------//
//----------------------Calendar--------------------//
//--------------------------------------------------//
    // standard browser sniffer class
    function Browser(){
      this.dom = document.getElementById?1:0;
      this.ie4 = (document.all && !this.dom)?1:0;
      this.ns4 = (document.layers && !this.dom)?1:0;
      this.ns6 = (this.dom && !document.all)?1:0;
      this.ie5 = (this.dom && document.all)?1:0;
      this.ok = this.dom || this.ie4 || this.ns4;
      this.platform = navigator.platform;
    }
    var browser = new Browser();

    var timeoutDelay = 500; // milliseconds before disappear
    var g_startDay = 1// 0=sunday, 1=monday

    // used by timeout auto hide functions
    var timeoutId = false;

    var builder = new StringBuilder();
    builder.a('<div id="calendarContainer" style="position:absolute; left: 100px; top: 100px; width: 124px; height: 132px;')
        .a('clip:rect(0px 124px 132px 0px); visibility : hidden; z-index : 4; background-color : #ffffff;" ')
        .a(' onmouseout="calendarTimeout();" onmouseover="if (timeoutId) clearTimeout(timeoutId);"></div>');
    document.write(builder.toString());

    var g_Calendar;  // global to hold the calendar reference, set by constructor

    function calendarTimeout() {
        timeoutId = setTimeout('g_Calendar.hide();',timeoutDelay);
    }

    // constructor for calendar class
    // shared singleton
    function Calendar() {
        g_Calendar = this;
        this.daysOfWeek = DAYSOFW;
        this.months = MONTHS;
        this.daysInMonth = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
        this.containerLayer = document.getElementById('calendarContainer');
    }

     Calendar.prototype.getFirstDOM = function() {
        var date = new Date();
        DateUtils.setDay(date, 1);
        DateUtils.setMonth(date, this.month);
        DateUtils.setYear(date, this.year);
        return date.getDay(); // day of week
    }

    Calendar.prototype.updatePopupContent = function() {
        var builder = new StringBuilder();
        builder.a('<form id="calendarForm" onSubmit="this.year.blur();return false;"><table width="100%" border="0" cellspacing="0" cellpadding="2" class="calBorderColor"><tr><td valign="top"><table width="100%" border="0" cellspacing="0" cellpadding="1" class="calBgColor">')
            .a('<tr><td width="60%" class="cal" align="left">')
            .a('<table border="0" cellspacing="0" cellpadding="0"><tr><td><a href="javascript: g_Calendar.changeMonth(-1);" onmouseover="window.status=\'Mois pr&eacute;c&eacute;dent\';return true;" onmouseout="window.status=\'\';return true;"><img name="calendar" src="').a(this.compoundDate.options.imgDir).a('/calendar/down.gif" width="8" height="12" border="0" alt=""></a></td><td class="cal" width="100%" align="center">').a(this.months[this.month - 1]).a('</td><td class="cal"><a href="javascript: g_Calendar.changeMonth(+1);" onmouseover="window.status=\'Mois suivant\';return true;" onmouseout="window.status=\'\';return true;"><img name="calendar" src="').a(this.compoundDate.options.imgDir).a('/calendar/up.gif" width="8" height="12" border="0" alt=""></a></td></tr></table>')
              .a('</td><td width="40%" align="right" class="cal">')
              .a('<table border="0" cellspacing="0" cellpadding="0"><tr><td class="cal"><a href="javascript: g_Calendar.changeYear(-1);" onmouseover="window.status=\'Ann&eacute;e pr&eacute;c&eacute;dente\';return true;" onmouseout="window.status=\'\';return true;"><img name="calendar" src="').a(this.compoundDate.options.imgDir).a('/calendar/down.gif" width="8" height="12" border="0" alt=""></a></td><td class="cal" width="100%" align="center">').a(this.year).a('</td><td class="cal"><a href="javascript: g_Calendar.changeYear(+1);" onmouseover="window.status=\'Ann&eacute;e suivante\';return true;" onmouseout="window.status=\'\';return true;"><img name="calendar" src="').a(this.compoundDate.options.imgDir).a('/calendar/up.gif" width="8" height="12" border="0" alt=""></a></td></tr></table>')
              .a('</td></tr></table>');

        var iCount = 1;
        var iFirstDOM = (7+this.getFirstDOM()-g_startDay)%7; // to prevent calling it in a loop
        var iDaysInMonth = DateUtils.getDaysInMonth(this.month, this.year);

        builder.a('<table width="100%" border="0" cellspacing="0" cellpadding="1" class="calBgColor"><tr>');
        for (var i=0;i<7;i++){
            builder.a('<td align="center" class="calDaysColor">').a(this.daysOfWeek[(g_startDay+i)%7]).a('</td>');
        }
        builder.a('</tr>');
        var fromComparInt = DateUtils.getComparInt(this.compoundDate.options.fromDate);
        var toComparInt = DateUtils.getComparInt(this.compoundDate.options.toDate);
        var iCount = 1;
        var cellDate = DateUtils.newDate(this.year, this.month, iCount);
        var cellComparInt = DateUtils.getComparInt(cellDate);
        for (var j=1;j<=6;j++) {
            builder.a('<tr>');
            for (var i=1;i<=7;i++) {
                builder.a('<td width="16" align="center" ');
                if ( (7*(j-1) + i)>=iFirstDOM+1  && iCount <= iDaysInMonth) {
                    if (this.day == iCount && this.year == this.compoundDate.getSelYear() && this.month == this.compoundDate.getSelMonth()) {
                        builder.a('class="calHighlightColor"');
                    } else {
                        if (i==7-g_startDay || i==((7-g_startDay)%7)+1) {
                            builder.a('class="calWeekend"');
                        } else {
                            builder.a('class="cal"');
                        }
                    }
                    builder.a('>');
                    if (cellComparInt >= fromComparInt && cellComparInt <= toComparInt) {
                        builder.a('<a class="cal" href="javascript: g_Calendar.clickDay(').a(iCount).a(');" onmouseover="window.status=\'').a(iCount).a(' ').a(this.months[this.month - 1]).a(' ').a(this.year).a('\';return true;" onmouseout="window.status=\'\';return true;">').a(iCount).a('</a>');
                    } else {
                        builder.a('<span class="disabled">').a(iCount).a('</span>');
                    }
                    iCount++;
                    DateUtils.setDay(cellDate, iCount);
                    cellComparInt = DateUtils.getComparInt(cellDate);
                } else {
                    if  (i==7-g_startDay || i==((7-g_startDay)%7)+1) {
                        builder.a('class="calWeekend"');
                    } else {
                        builder.a('class="cal"');
                    }
                    builder.a('>&nbsp;');
                }
                builder.a('</td>');
            }
            builder.a('</tr>');
        }
        builder.a('</table></td></tr></table></form>');
        this.containerLayer.innerHTML = builder.toString();
    }
    Calendar.prototype.changeYear = function(incr){
       (incr==1)?this.year++:this.year--;
       this.updatePopupContent();
    }
    Calendar.prototype.changeMonth = function(incr){
        if (this.month == 12 && incr == 1){
            this.month = 1;
            this.year++;
        } else {
            if (this.month==1 && incr==-1){
                this.month = 12;
                this.year--;
            } else {
                (incr == 1) ? this.month++ : this.month--;
            }
        }
       this.updatePopupContent();
    }

    Calendar.prototype.clickDay = function(day){
       this.compoundDate.setDateParts(this.year, this.month, day);
       this.hide();
    }

    Calendar.prototype.show = function(event, compoundDate) {
        if (this.containerLayer.style.visibility=='visible') {
            this.containerLayer.style.visibility='hidden';
            this.compoundDate.calendarHidden();
            return;
        }

        if (compoundDate.options.anchorElement) {
            var anchor = compoundDate.options.anchorElement;
            var leftPos = anchor.getLeft() + anchor.offsetWidth;
            var topPos = anchor.getTop();
            PositionUtils.setPosition(this.containerLayer, leftPos, topPos);
        } else {
            PositionUtils.setPosition(this.containerLayer,
                PositionUtils.mouseX + 5, PositionUtils.mouseY - 15);
        }

        // values init using the compoundDate
        this.compoundDate = compoundDate;
        this.month = compoundDate.getSelMonth();
        this.day = compoundDate.getSelDay();
        this.year = compoundDate.getSelYear();
           this.updatePopupContent();

        this.containerLayer.style.visibility='visible';
    }

    Calendar.prototype.hide = function() {
        this.containerLayer.style.visibility='hidden';
        if (this.compoundDate != null) {
            this.compoundDate.calendarHidden();
            this.compoundDate = null;
        }
    }

    function handleDocumentClick(e){
      if (browser.ie4 || browser.ie5) e = window.event;

      if (browser.ns6){
          if (g_Calendar != null){
            var bTest = (e.pageX > parseInt(g_Calendar.containerLayer.style.left,10) && e.pageX <  (parseInt(g_Calendar.containerLayer.style.left,10)+125) && e.pageY < (parseInt(g_Calendar.containerLayer.style.top,10)+125) && e.pageY > parseInt(g_Calendar.containerLayer.style.top,10));
            if (e.target.id.toLowerCase().indexOf("calendarimg") == -1 && e.target.name!='month'  && e.target.name!='year' && e.target.name!='calendar' && e.target.className != "cal" && !bTest){
              g_Calendar.hide();
            }
        }
      }
      if (browser.ie4 || browser.ie5){
          if (g_Calendar != null){
        // if user clicked inside the calendar & outside a valid date, it doesn't disappear
       var bTest = (e.x > parseInt(g_Calendar.containerLayer.style.left,10) && e.x <  (parseInt(g_Calendar.containerLayer.style.left,10)+125) && e.y < (parseInt(g_Calendar.containerLayer.style.top,10)+125) && e.y > parseInt(g_Calendar.containerLayer.style.top,10));
        if (e.srcElement.id.toLowerCase().indexOf("calendarimg") == -1 && e.srcElement.name!='month' && e.srcElement.name!='year' && e.srcElement.className != "cal" && !bTest & typeof(e.srcElement)!='object'){
          g_Calendar.hide();
         }
        }
      }
      if (browser.ns4) g_Calendar.hide();
    }

      // Finally licked extending native date object;
      Date.isLeapYear = function(year){ if (year%4==0 && ((year%100!=0) || (year%400==0))) return true; else return false; }
      Date.daysInYear = function(year){ if (Date.isLeapYear(year)) return 366; else return 365;}
      var DAY = 1000*60*60*24;
      Date.prototype.addDays = function(num){
        return new Date((num*DAY)+this.valueOf());
      }
    window.onloadCal=function(){
      new Calendar();
    }
    window.document.onclick=handleDocumentClick;
