/*****************************************************
* Maintains a clock with location and GMT time offset
*****************************************************/
function Clock(/* String */ city, /* Float */ gmtOffset) {
	dateobj = new Date();
	
	this.location = city;
	this.clientOffsetMsecs = dateobj.getTimezoneOffset() * 60000;
	this.gmtOffsetMsecs = gmtOffset * 3600000;
	this.last_time = null;
}

//Displays the given time on the clock
Clock.prototype.displayTime = function() {
	var currTime = new Date();
	var zoneTime = currTime.valueOf() + this.gmtOffsetMsecs + this.clientOffsetMsecs;
	var location_id = this.location.replace(' ','_');
	
	//if last time displayed was more than 5 minutes ago
	if(!this.last_time || zoneTime - this.last_time > 300000)
	{
		// get the element objects
		var objHour = document.getElementById(location_id + '_hours');
		var objMinutes = document.getElementById(location_id + '_minutes');
		if (!objHour || !objMinutes) { return; }

		// round the time to nearest 5 minutes
		var nRound = 300000;
		var nDiff = zoneTime % nRound;
		if(nDiff != 0)
		{
			if (nDiff < 180000) { zoneTime -= nDiff; } // < 3 minutes round down
			else { zoneTime += nRound - nDiff; } // > 3 minutes round up
		}
		
		// create new Date element using display time
		currTime.setTime(zoneTime);
	
		// Update the on page elements
		/* DAYLIGHT SAVINGS TIME HACK -- FIX THIS */
		objHour.className = 'hours hr' + (currTime.getHours() % 12 + 1);
		objMinutes.className = 'minutes min' + currTime.getMinutes();
	
		//save the last displayed time
		this.last_time = currTime;
	}
	
	//Update the clock every minute
	var clock = this;
	setTimeout(function() { clock.displayTime(); }, 60000);
}

//Returns the last time displayed on the clock
Clock.prototype.getLastTime = function() {
	return this.last_time;
}

//Returns the offset from GMT to the location timezone in hours
Clock.prototype.getGMTOffset = function() {
	//return this.gmtOffsetMsecs / 60000;
	var tzdetect = DstDetect();

return TimezoneDetect();

}

//Return HTML representation of this clock
Clock.prototype.getHTML = function() {
	var location_id = this.location.replace(' ','_');

	// Create DOM Elements
	var clock = document.createElement("div");
	clock.setAttribute("id", location_id + '_clock');
	clock.setAttribute("class", "clock_container");
	var base = document.createElement("div");
	base.setAttribute("id", location_id + '_clockbase');
	base.setAttribute("class", 'clockbase');
	var hours = document.createElement("div");
	hours.setAttribute("id", location_id + '_hours');
	hours.setAttribute("class", "hours");
	var minutes = document.createElement("div");
	minutes.setAttribute("id", location_id + '_minutes');
	minutes.setAttribute("class", "minutes");
	var label = document.createElement("div");
	label.setAttribute("class", "clock_label");
	var labelText = document.createTextNode(this.location);
	
	// Nest DOM Elements from the bottom up
	base.appendChild(hours);
	base.appendChild(minutes);
	clock.appendChild(base);
	label.appendChild(labelText);
	clock.appendChild(label);

	return clock;
}

/*****************************************************
* A container class to manage multiple clocks
* 
* Must be passed an ID for a div container to
* hold all clocks.
* 
* Optionally accepts a preformed array of Clocks
*****************************************************/
function ClockManager(/* Div Container ID */ div, /* Clock Array */ clocks) {
	this.container = div;
	this.clocks = clocks || [];
}

ClockManager.prototype.addClock = function(/* String */  city, /* Float */ gmtOffset) {
	var clock = new Clock(city, gmtOffset);
	
	//insert new clock HTML
	var html = clock.getHTML();
	document.getElementById(this.container).appendChild(html);
	
	clock.displayTime();
	this.clocks.push(clock);
}

//Find start and end of DST
function DstDetect(){
    var dtDstDetect = new Date();
    var dtDstStart = '';
    var dtDstEnd = '';
    var dtDstStartHold = ''; //Temp date hold
    var intYearDayCount = 732; //366 (include leap year) * 2 (for two years)
    var intHourOfYear = 1;
    var intDayOfYear;
    var intOffset = TimezoneDetect(); //Custom function. Make sure you include it.
 
    //Start from a year ago to make sure we include any previously starting DST
    dtDstDetect = new Date()
    dtDstDetect.setUTCFullYear(dtDstDetect.getUTCFullYear() - 1);
    dtDstDetect.setUTCHours(0,0,0,0);
 
    //Going hour by hour through the year will detect DST with shorter code but that could result in 8760
    //FOR loops and several seconds of script execution time. Longer code narrows this down a little.
    //Go one day at a time and find out approx time of DST and if there even is DST on this computer.
    //Also need to make sure we catch the most current start and end cycle.
    for(intDayOfYear = 1; intDayOfYear <= intYearDayCount; intDayOfYear++){
        dtDstDetect.setUTCDate(dtDstDetect.getUTCDate() + 1);
 
        if ((dtDstDetect.getTimezoneOffset() * (-1)) != intOffset && dtDstStartHold == ''){
            dtDstStartHold = new Date(dtDstDetect);
        }
        if ((dtDstDetect.getTimezoneOffset() * (-1)) == intOffset && dtDstStartHold != ''){
            dtDstStart = new Date(dtDstStartHold);
            dtDstEnd = new Date(dtDstDetect);
            dtDstStartHold = '';
 
            //DST is being used in this timezone. Narrow the time down to the exact hour the change happens
            //Remove 48 hours (a few extra to be on safe side) from the start/end date and find the exact change point
            //Go hour by hour until a change in the timezone offset is detected.
            dtDstStart.setUTCHours(dtDstStart.getUTCHours() - 48);
            dtDstEnd.setUTCHours(dtDstEnd.getUTCHours() - 48);
 
            //First find when DST starts
            for(intHourOfYear=1; intHourOfYear <= 48; intHourOfYear++){
                dtDstStart.setUTCHours(dtDstStart.getUTCHours() + 1);
 
                //If we found it then exit the loop. dtDstStart will have the correct value left in it.
                if ((dtDstStart.getTimezoneOffset() * (-1)) != intOffset){
                    break;
                }
            }
 
            //Now find out when DST ends
            for(intHourOfYear=1; intHourOfYear <= 48; intHourOfYear++){
                dtDstEnd.setUTCHours(dtDstEnd.getUTCHours() + 1);
 
                //If we found it then exit the loop. dtDstEnd will have the correct value left in it.
                if ((dtDstEnd.getTimezoneOffset() * (-1)) != (intOffset + 60)){
                    break;
                }
            }
 
            //Check if DST is currently on for this time frame. If it is then return these values.
            //If not then keep going. The function will either return the last values collected
            //or another value that is currently in effect
            if ((new Date()).getTime() >= dtDstStart.getTime() && (new Date()).getTime() <= dtDstEnd.getTime()){
                return new Array(dtDstStart,dtDstEnd);
            }
 
        }
    }
    return new Array(dtDstStart,dtDstEnd);
}

function TimezoneDetect(){
    var dtDate = new Date('1/1/' + (new Date()).getUTCFullYear());
    var intOffset = 10000; //set initial offset high so it is adjusted on the first attempt
    var intMonth;
    var intHoursUtc;
    var intHours;
    var intDaysMultiplyBy;
 
    //go through each month to find the lowest offset to account for DST
    for (intMonth=0;intMonth < 12;intMonth++){
        //go to the next month
        dtDate.setUTCMonth(dtDate.getUTCMonth() + 1);
 
        //To ignore daylight saving time look for the lowest offset.
        //Since, during DST, the clock moves forward, it'll be a bigger number.
        if (intOffset > (dtDate.getTimezoneOffset() * (-1))){
            intOffset = (dtDate.getTimezoneOffset() * (-1));
        }
    }
 
    return intOffset;
}

