//Constants:
var DATETIME_YEARS_BACK    = 0;
var DATETIME_YEARS_FORWARD = 10;
var firstYear;
var lastYear;

//Constructor:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function DateTimePicker(name)
{
    this.prefix    = "DateTimePicker_";

	// Mix in some utility methods and standard properties relating to time handling.
	DateTimePickerMixin(this, name);

    this.pairCtl    = document.getElementById(name + '_paired_control');
    this.ddYear     = document.getElementById(prefix+name+'_year');
    this.ddMonth    = document.getElementById(prefix+name+'_month');
    this.ddDate     = document.getElementById(prefix+name+'_date');
    this.ddDay      = document.getElementById(prefix+name+'_day');
    this.ddHour     = document.getElementById(prefix+name+'_hour');
    this.ddMinute   = document.getElementById(prefix+name+'_minute');
    this.trNormal   = document.getElementById(prefix+name+'_normal');
    this.trEdit     = document.getElementById(prefix+name+'_edit');

    this.InitialiseDropdowns();

	// Set the default date if it has been provided, or set it to nothing
	// if the special default value "none" has been provided.
	if ( this.hidden.value.toLowerCase() != "none" ) { 
    	this.SetNewDate( this.hidden.value );
	}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//Events:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.onchange = function () {}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//Public
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.SetNewDate = function(dateStringOrObject)
{
    var tempDate = this.ParseDateTimeFromString(dateStringOrObject);
    var test = tempDate.toString();
    if (('NaN' != test)&&('Invalid Date' != test)) 
    {   this.value = tempDate;    }

    this.ApplyDate();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.ApplyDate = function(blnSync)
{
    this.SetDDYear( this.GetY2kYear(this.value.getYear()) );
    this.SetDDMonth( this.value.getMonth()+1 );
    this.SetDDDate( this.value.getDate() );
    this.SetDDHour( this.value.getHours() );
    this.SetDDMinute( this.value.getMinutes() );
    this.SetDDQHour( this.value.getHours() + ':' + this.value.getMinutes() );
    this.SetDDAmPm( this.value.getHours() );
    
    this.ChangeYear(blnSync);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.Show = function()
{   this.trNormal.style.display = 'none'; this.trEdit.style.display   = ''; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.Hide = function()
{   this.trEdit.style.display   = 'none'; this.trNormal.style.display = ''; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.ChangeYear = function(blnSync)
{   
    var year = this.GetDDValue(this.ddYear, this.GetY2kYear(this.value.getYear()) );

    this.value.setYear(year);
    this.ResetDDYears(year);
    this.ChangeMonth(blnSync);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.ChangeMonth = function(blnSync)
{   
    var month = this.GetDDValue( this.ddMonth, this.value.getMonth()+1 ) - 1;

    //Scale the day value back if the new month has less days (date object behaves unpredictably)
    var maxDate = this.GetMaxDateOfMonth( month, this.value.getYear() );
    if ( this.value.getDate() > maxDate )
    {
		this.value.setDate( maxDate );
		this.SetDDDate(maxDate);
	}

    this.value.setMonth(parseInt(month));

	// Rebuild the day and day-of-week lists
    var date = this.GetDDValue( this.ddDate, this.value.getDate() );
    this.ResetDDDates(date);

	// Change the date select
    this.ChangeDate(blnSync);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.ChangeDate = function(blnSync)
{   
    var date = this.GetDDValue( this.ddDate, this.value.getDate() );
    this.value.setDate(date);
    this.ddDay.selectedIndex = this.ddDate.selectedIndex;
    this.ChangeHour(blnSync);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.ChangeDay = function(blnSync)
{   
    this.ddDate.selectedIndex = this.ddDay.selectedIndex;
    this.ChangeDate(blnSync);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.ChangeHour = function(blnSync)
{   
	// If there's no hour field, then try changing the quarter hour field instead.
	if (this.ddHour) { 
	    var hour = this.GetDDValue( this.ddHour, this.value.getHours() );
		// Check to see if it's AM or PM.
		if (!this.IsAm() && hour < 12) { hour += 12; }
		else if (this.IsAm() && hour == 12) { hour = 0; }
	    this.value.setHours(hour);
	    this.ChangeMinute(blnSync);
	} // Change the quarter hour value if available.
	else if (this.ddQHour) {
		this.ChangeQuarterHour(blnSync);
	}
	else { // Otherwise just update the hidden value.
	    this.ChangeHidden(blnSync);		
	}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.ChangeMinute = function(blnSync)
{   
    var minute = this.GetDDValue( this.ddMinute, this.value.getMinutes() );
	if (minute) {
		this.value.setMinutes( minute)
	}
    this.ChangeHidden(blnSync);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.ChangeHidden = function(blnSync)
{
    this.hidden.value = this.FormatDateTimeString(this.value);  //Default date format
    this.onchange();

	// This date control may be one of a pair of controls, so try calling the synchronise method
	// if it exists, but only if requested to avoid infinite loops.
	if (blnSync) {
		try {
			SynchroniseDatePairHandler(this.hidden.id, this.hidden.id);
		}
		catch (e) {}
	}
}

//Private
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.InitialiseDropdowns = function()
{
    //Months:
    var dd = this.ddMonth;
    if (dd.options.length == 0) {
	    for (var i=1; i<=12; i++)
	    {
	        var tempDate = new Date(i+'-01-1976');
	        tempDate.setYear( this.GetY2kYear(this.value.getYear()) );
	        tempDate.setDate(1);
	        tempDate.setMonth(i-1);
	        var month    = this.GetDateField(tempDate,1);
	        dd.options[dd.options.length] = new Option(month, i);
	    }
	}
    
    //Hours:
    var dd = this.ddHour;
	if (dd) {
    	dd.options.length = 0;
    	for (var i=1; i<=12; i++)
    	{
        	if (i<10)       {   var j = '0' + i; }
        	else            {   var j = ''  + i; }
        	dd.options[dd.options.length] = new Option(j, i);
    	}
	}
	
    //Minutes:
	var dd = this.ddMinute;
	if (dd) {
	    dd.options.length = 0;
	    for (var i=0; i<60; i++)
	    {
	        if (i<10)   {  var j = '0' + i; }
	        else        {  var j = ''  + i; }
	        dd.options[dd.options.length] = new Option(j, i);
	    }
	}
    //QuarterHour:

    var dd = this.ddQHour;
	if (dd && dd.options.length == 0) {
		var strVal;
	    for (var i=1; i<=12; i++)
	    {
	        if (i<10)   {  var j = '0' + i; }
	        else        {  var j = ''  + i; }
	        dd.options[dd.options.length] = new Option(j + ':00', i + ':00');
	        dd.options[dd.options.length] = new Option(j + ':15', i + ':15');
	        dd.options[dd.options.length] = new Option(j + ':30', i + ':30');
	        dd.options[dd.options.length] = new Option(j + ':45', i + ':45');
	    }
	}

}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.ResetDDYears = function(year)
{
	// Get the year control.
    var dd = this.ddYear;
	
	// Get the current year and set the year range.
	now = new Date();
    startYear = parseInt(this.GetY2kYear(now.getYear()));
	firstYear = startYear - DATETIME_YEARS_BACK;
	lastYear = startYear + DATETIME_YEARS_FORWARD;
    dd.options.length = 0;
    for (i=firstYear;i<=lastYear;i++)
    {    dd.options[dd.options.length] = new Option(i,i); }
	
	// Set the selected year to the specified year. 
    this.SetDDYear(year);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.ResetDDDates = function(date)
{
    var ddDate  = this.ddDate;
    var ddDay   = this.ddDay;

    var maxDate = this.GetMaxDateOfMonth(this.value.getMonth(), this.GetY2kYear(this.value.getYear()));
    var tempDate = new Date();
    tempDate.setYear( this.GetY2kYear(this.value.getYear()) );
    tempDate.setMonth(this.GetDDValue(this.ddMonth, null)-1);

    ddDate.options.length = 0;
    ddDay.options.length = 0;
    for (var i=1; i<=maxDate;i++)
    {
        if (i<10)   {  var j = '0' + i; }
        else        {  var j = ''  + i; }
        ddDate.options[ddDate.options.length] = new Option(j, i);

        tempDate.setDate( i );
        ddDay.options[ddDay.options.length] = new Option( this.GetDateField(tempDate,0), i );
    }
    this.SetDDValue(ddDate, date);
    this.SetDDValue(ddDay,  date);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.SetDDYear    = function(year)
{   this.SetDDValue( this.ddYear, year);  }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.SetDDMonth   = function(month)
{   this.SetDDValue( this.ddMonth, month);  }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.SetDDDate   = function(date)
{
    date = new String(date);
    this.SetDDValue( this.ddDate, date);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.SetDDHour    = function(hour)
{
    hour = parseInt(hour);
    if ( hour > 12 )  {   hour = hour - 12; }
    this.SetDDValue( this.ddHour, hour);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DateTimePicker.prototype.SetDDMinute  = function(minute)
{
    minute = parseInt(minute);
    this.SetDDValue( this.ddMinute, minute);
}

