/**
 * The DatePicker object
 * 
 * Dependancies:
 *    - Date.js
 *    - Calendar.js
 * 
 * @author Michael Mifsud
 * @notes Based on the DatePicker code by Richard Heyes.
 * @package DatePicker
 */


// <script language="javascript" type="text/javascript" src="js/DhtmlLayer.js"></script>


/**
 * __construct
 * 
 * @param string objName - The name you called this object.
 * @param string callbackFunction - The function that gets called when an event occurs.
 */
DatePicker.Extends(DhtmlLayer);
function DatePicker(objName, callbackFunction) {
    
    this.DhtmlLayer(objName);      // parent::__construct
    this.imgIcon   = arguments[2] != null ? arguments[2] : 'images/blank.gif';
    
    // Properties
    this.callbackFunction   = callbackFunction;
    
    this.dateFrom           = new Date();
    this.dateFrom           = this.dateFrom.noon();
    this.dateFrom           = this.dateFrom.addMonths(-30);  // default 2 1/2 years in past
    
    this.dateTo             = new Date();
    this.dateTo             = this.dateTo.noon();
    this.dateTo             = this.dateTo.addMonths(30);     // default 2 1/2 years in future
    
    this.selectedDate       = new Date();   // The default selected date 
    this.selectedDate       = this.selectedDate.noon();
    
    
    // __construct
    this.setCssClass('datePicker');
    this.writeLayerHTML();
    //vd(this.parent);
    //this.writeLayerDOM(getElementById(objName));
    
    // Hack to enable iframe mask for ie...
    if (sniffer.is_ie) {
        this.setLayerDimension('7.2em', '11.0em');
    }
    
    document.addOnClickHandler(this.objName+'.hide');
    
}


/**
 * Show a calendar div
 * 
 * @param integer month - (optional) Where 0 = jan, 11 = dec.
 * @param integer year  - (optional) Where in format of 2005.
 * @param integer day   - (optional) Month date 1-31
 */
DatePicker.Override(DhtmlLayer, 'show');
DatePicker.prototype.show = function() {
    
    var year  = arguments[0] != null ? arguments[0] : this.selectedDate.getFullYear();
    var month = arguments[1] != null ? arguments[1] : this.selectedDate.getMonth();
    var day   = arguments[2] != null ? arguments[2] : this.selectedDate.getDate();
    // Get a fresh CalendarMonth object
    var calendar = this.getCalendarMonth(month, year, day);
    // Set the selected date
    //this.setSelectedDate(new Date(year, month, day, 12, 0, 0));
    
    // Build html for layer object
    var html = '<table border="0" cellpadding="1" cellspacing="0"  class="dpDatePicker">';
    
    html += this.getNavHtml(calendar);
    
    html += this.getMonthsHtml(calendar);
    
    html += this.getCalendarHtml(calendar);
    
    
    html += '</table>';
    this.setHTML(html);
    
    // Call show() method
    this.DhtmlLayer_show();
}

DatePicker.Override(DhtmlLayer, 'hide');
DatePicker.prototype.hide = function() {
    var force   = arguments[0] != null ? arguments[0] : false;
    if (!this.isMouseover || force) {
        this.DhtmlLayer_hide();
    }
}

/**
 * Set the selected date
 * 
 * @param integer month - Where 0 = jan, 11 = dec.
 * @param integer year  - Where in format of 2005.
 * @param integer day   - Month date 1-31
 */
DatePicker.prototype.setSelectedDate = function(date) {
    if (date < this.dateFrom) {
        date = this.dateFrom.clone();
    } else if (date > this.dateTo) {
        date = this.dateTo.clone();
    }
    this.selectedDate = date;
}


////////////////// Private Methods /////////////////

/**
 * Get a new calendar object and update the currently selected
 *  date/day (this.selectedDate).
 * 
 * @param integer month - (0 = jan, 11 = dec)
 * @param integer year - (Fullyear: 2005)
 */
DatePicker.prototype.getCalendarMonth = function(month, year, day) {
    var cal = new CalendarMonth(month, year);
    // Update the selected date
    var date = cal.getDate();
    date.setDate(this.selectedDate.getDate());
    
    return cal;
}


/**
 * Generate the html the top nav bar
 * 
 * @param CalendarMonth calendar - A calendar object
 * @return string
 * @todo instead of disabling next/last year, make it go to dateTo,
 *    disable if on that month
 */
DatePicker.prototype.getNavHtml = function(calendar) {
    
    var today     = new Date();
    var calDate   = calendar.getDate();
    var prevMonth = calDate.addMonths(-1);
    var nextMonth = calDate.addMonths(1);
    var prevYear  = calDate.addYears(-1);
    var nextYear  = calDate.addYears(1);
    
    var jsPrevMonth   = this.objName+'.show('+prevMonth.getFullYear()+', '+prevMonth.getMonth()+');';
    var jsNextMonth   = this.objName+'.show('+nextMonth.getFullYear()+', '+nextMonth.getMonth()+');';
    var jsPrevYear    = this.objName+'.show('+prevYear.getFullYear()+', '+prevYear.getMonth()+');';
    var jsNextYear    = this.objName+'.show('+nextYear.getFullYear()+', '+nextYear.getMonth()+');';
    var jsToday       = this.objName+'.show('+today.getFullYear()+', '+today.getMonth()+');';
    var jsDateFrom    = this.objName+'.show('+this.dateFrom.getFullYear()+', '+this.dateFrom.getMonth()+');';
    var jsDateTo      = this.objName+'.show('+this.dateTo.getFullYear()+', '+this.dateTo.getMonth()+');';
    
    var html = '<tr><td>';
    html += '<table border="0" cellpadding="1" cellspacing="1" class="dpNav" align="center">';
    
    html += '<tr>';
    
    var btnJs = 'onmousedown="this.className = \'dpNavBtnDown\';" onmouseup="this.className = \'dpNavBtnUp\';" '+
                'onmouseover="this.className = \'dpNavBtnUp\';"';
    // Check if year/month is in range dissable if not
    if (prevYear < this.dateFrom.getFirstDayOfMonth()) {
        if (prevMonth < this.dateFrom.getFirstDayOfMonth()) {
            html += '<td class="dpNavPrevYear" onmouseout="this.className = \'dpNavPrevYear\';" ' + btnJs +
                    '><a title="Previous Year." href="javascript: ;" class="disable" onclick="this.blur();">&#171;</a></td>';
        }else{
            html += '<td class="dpNavPrevYear" onmouseout="this.className = \'dpNavPrevYear\';" ' + btnJs +
                    ' onclick="'+jsDateFrom+'"><a title="Previous Year." href="javascript: '+jsDateFrom+'">&#171;</a></td>';
        }
    } else {
        html += '<td class="dpNavPrevYear" onmouseout="this.className = \'dpNavPrevYear\';" ' + btnJs +
                ' onclick="'+jsPrevYear+'"><a title="Previous Year." href="javascript: '+jsPrevYear+'">&#171;</a></td>';
    }
    if (prevMonth < this.dateFrom.getFirstDayOfMonth()) {  // test if month is in range
        html += '<td class="dpNavPrevMonth" onmouseout="this.className = \'dpNavPrevMonth\';" ' + btnJs +
                '><a title="Previous Month." href="javascript: ;" class="disable" onclick="this.blur();">&#8249;</a></td>';
    } else {
        html += '<td class="dpNavPrevMonth" onmouseout="this.className = \'dpNavPrevMonth\';" ' + btnJs +
                ' onclick="'+jsPrevMonth+'"><a title="Previous Month." href="javascript: '+jsPrevMonth+'">&#8249;</a></td>';
    }
    
    
    html += '<td class="dpNavCell" width="100%" align="center" onmouseout="this.className = \'dpNavCell\';" ' + 
            btnJs + ' onclick="'+jsToday+'"><a title="Go To Today." href="javascript: '+jsToday+'">'+
            calDate.getMonthAbbreviation()+' '+calDate.getFullYear()+'</a></td>';
    
    
    // Check if year/month is in range dissable if not
    if (nextMonth >= this.dateTo.getLastDayOfMonth()) { 
        html += '<td class="dpNavNextMonth" onmouseout="this.className = \'dpNavNextMonth\';" ' + btnJs +
                '><a title="Next Month." href="javascript: ;" class="disable" onclick="this.blur();">&#8250;</a></td>';
    } else {
        html += '<td class="dpNavNextMonth" onmouseout="this.className = \'dpNavNextMonth\';" ' + btnJs +
                ' onclick="'+jsNextMonth+'"><a title="Next Month." href="javascript: '+jsNextMonth+'">&#8250;</a></td>';
    }
    if (nextYear >= this.dateTo.getLastDayOfMonth()) {
        if (nextMonth >= this.dateTo.getLastDayOfMonth()) { 
            html += '<td class="dpNavNextYear" onmouseout="this.className = \'dpNavNextYear\';" ' + btnJs +
                    '><a title="Next Year." href="javascript: ;" class="disable" onclick="this.blur();">&#187;</a></td>';
        }else{
            html += '<td class="dpNavNextYear" onmouseout="this.className = \'dpNavNextYear\';" ' + btnJs +
                ' onclick="'+jsDateTo+'"><a title="Next Year." href="javascript: '+jsDateTo+'">&#187;</a></td>';
        }
    } else {
        html += '<td class="dpNavNextYear" onmouseout="this.className = \'dpNavNextYear\';" ' + btnJs +
                ' onclick="'+jsNextYear+'"><a title="Next Year." href="javascript: '+jsNextYear+'">&#187;</a></td>';
    }
    
    html += '</tr>';
    
    html += '</table>';
    html += '</td></tr>';
    
    return html;
}


/**
 * Generate the html for a clickable calendar.
 * 
 * @param CalendarMonth calendar - A calendar object
 * @return string
 */
DatePicker.prototype.getMonthsHtml = function(calendar) {
    var date = new Date(calendar.year, 1, 1, 12, 0, 0);
    var js = '';
    var html = '<tr><td>';
    html += '<table border="0" cellpadding="1" cellspacing="0" class="dpMonths" align="center">';
    
    html += '<tr>';
    for(i = 0; i < 12; i++) {
        date = new Date(calendar.year, i, 1, 12, 0, 0);
        if ((i % 6) == 0) {
            html += '</tr><tr>';
        }
        js = this.objName+'.show('+calendar.year+', '+i+');';
        //alert('Date: ' + date + '\ndateFrom: ' + this.dateFrom + '\ndateTo: ' + this.dateTo);
        if (date < this.dateFrom.getFirstDayOfMonth() || date > this.dateTo.getLastDayOfMonth()) {
            html += '<td class="dpMonth" onmouseover="this.className = \'dpMonthHover\';" ' +
            'onmouseout="this.className = \'dpMonth\';">' +
            '<a title="'+date.getMonthName(i)+' '+calendar.year+'" class="disable" href="javascript: ;" onclick="this.blur();">';
            html += date.getMonthAbbreviation(i);
            html += '</a></td>';
        }else{
            html += '<td class="dpMonth" onmouseover="this.className = \'dpMonthHover\';" ' +
            'onmouseout="this.className = \'dpMonth\';" onclick="'+js+'">' +
            '<a title="'+date.getMonthName(i)+' '+calendar.year+'" href="javascript: '+js+'">';
            html += date.getMonthAbbreviation(i);
            html += '</a></td>';
        }
    }
    html += '</tr>';
    
    html += '</table>';
    html += '</td></tr>';
    
    return html;
}


/**
 * Generate the html for the days in the calendar.
 * 
 * @param CalendarMonth calendar - A calendar object
 * @return string
 */
DatePicker.prototype.getCalendarHtml = function(calendar) {
    var weeks = calendar.weekDates;
    
    var html = '<tr><td>';
    html += '<table border="0" cellpadding="1" cellspacing="0"  class="dpCalendar" align="center">';
    // Add weekday names
    html += '<tr>';
    for (i = 0; i < calendar.dayNames.length; i++) {
        html += '<td class="dpDayName">'+calendar.dayNames[i]+'</td>';
    }
    html += '</tr>';
    
    // Add the days to the table
    for (i = 0; i < weeks.length; i++) {
        html += '<tr>';
        week = weeks[i];
        // Add the day links
        for(j = 0; j < 7; j++) {
            day = week[j];
            html += this.getDayHtml(calendar, day);
        }
        html += '</tr>';
    }
    
    html += '</table>';
    html += '</td></tr>';
    
    
    return html;
}
/**
 * Create a day link
 * 
 * @param CalendarMonth calendar - 
 * @param CalendarDay day - 
 * @return string
 */
DatePicker.prototype.getDayHtml = function(calendar, day) {
    var html = '';
    if (day.value == 0) {
        return '<td class="dpDayDisable" onclick="this.blur();">&nbsp;</td>';
    }
    dayDate = calendar.getDate();
    dayDate.setDate(day.getValue());
    
    var js = this.callbackFunction+'('+calendar.year+','+calendar.month+','+day.getValue()+');';
    js += this.objName+'.hide(true);';
    var mouseover = 'this.className = dpDayHover';
    var mouseout = '';
    
    if (dayDate < this.dateFrom || dayDate > this.dateTo) {
        html = '<td class="dpDay" onmouseover="this.className = \'dpDayHover\';"' + 
                'onmouseout="this.className = \'dpDay\';">' +
                '<a href="javascript: ;" class="disable" onclick="this.blur();">'+day.getValue()+'</a></td>';
    } else if (this.isDaySelected(calendar, day)) 
    {
        html = '<td class="dpDaySelected" onmouseover="this.className = \'dpDayHover\';"' +
                 'onmouseout="this.className = \'dpDaySelected\';" onclick="'+js+'">' +
                 '<a href="javascript: '+js+'">'+day.getValue()+'</a></td>';
    } else if (this.isToday(calendar, day)) {
        html = '<td class="dpDayToday" onmouseover="this.className = \'dpDayHover\';"' +
                  'onmouseout="this.className = \'dpDayToday\';" onclick="'+js+'">' +
                  '<a href="javascript: '+js+'"">'+day.getValue()+'</a></td>';
    } else {
        
        if (dayDate.getDay() == 0 || dayDate.getDay() == 6) {
            html = '<td class="dpDayWeekend" onmouseover="this.className = \'dpDayHover\';" ' + 
                   'onmouseout="this.className = \'dpDayWeekend\';" onclick="'+js+'">' +
                   '<a href="javascript: '+js+'">'+day.getValue()+'</a></td>';
        }else{
            html = '<td class="dpDay" onmouseover="this.className = \'dpDayHover\';" ' + 
                   'onmouseout="this.className = \'dpDay\';" onclick="'+js+'">' +
                   '<a href="javascript: '+js+'">'+day.getValue()+'</a></td>';
        }
    }
    
    return html;
}

/**
 * Returns true if this day is the user selected day.
 * 
 * @param CalendarMonth calendar - 
 * @param CalendarDay day - 
 * @return boolean
 */
DatePicker.prototype.isDaySelected = function(calendar, day) {
    return (calendar.year == this.selectedDate.getFullYear() &&
        calendar.month == this.selectedDate.getMonth() &&
        day.value == this.selectedDate.getDate());
}

/**
 * Returns true if this day is today
 * 
 * @param CalendarMonth calendar - 
 * @param CalendarDay day - 
 * @return boolean
 */
DatePicker.prototype.isToday = function(calendar, day) {
    var date = new Date();
    return (calendar.year == date.getFullYear() &&
        calendar.month == date.getMonth() &&
        day.value == date.getDate());
}

