var monthNames = new Array ("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
var monthNumbers = { Jan:0,Feb:1,Mar:2,Apr:3,May:4,Jun:5,Jul:6,Aug:7,Sep:8,Oct:9,Nov:10,Dec:11 };
var dayNames = new Array ("Sun","Mon","Tue","Wed","Thu","Fri","Sat");
var dayNumbers = { Sun:0,Mon:1,Tue:3,Wed:4,Thu:5,Fri:6,Sat:7 };
var Jan=0,Feb=1,Mar=2,Apr=3,May=4,Jun=5,Jul=6,Aug=7,Sep=8,Oct=9,Nov=10,Dec=11;
var Sun=0,Mon=1,Tue=2,Wed=3,Thu=4,Fri=5,Sat=6;
var now = new Date ();
var year = now.getFullYear();
var cities = new Array ();

function getTheDateFor (_rule)
	{
	var month = 0, day=0;

	// find the month
	for (i = 0; i < 12; ++i)
		if (_rule.indexOf(monthNames[i]) > -1)
			{
			// set month from month name in the rule
			month = i;

			// set day from date in the rule
			var sub1 = _rule.substr(_rule.indexOf(monthNames[i]));
			var sub2 = sub1.substr(sub1.indexOf(" "));
			day = parseInt(sub2);
			}

	if (!isNaN(day))
		{
		// day has already been set from the rule
		}
	else if (_rule.indexOf("first") > -1)
		{
		day = 1;
		while (1)
			{
			var date = new Date (year, month, day);
			var dow = date.getDay();
			if (dow == dayNumbers.Sun)
				break;
			++day;
			}
		// day is now date of 1st Sunday
		}
	else if (_rule.indexOf("second") > -1)
		{
		day = 7;
		while (1)
			{
			var date = new Date (year, month, day);
			var dow = date.getDay();
			if (dow == dayNumbers.Sun)
				break;
			++day;
			}
		// day is now date of 2nd Sunday
		}
	else if (_rule.indexOf("third") > -1)
		{
		day = 14;
		while (1)
			{
			var date = new Date (year, month, day);
			var dow = date.getDay();
			if (dow == dayNumbers.Sun)
				break;
			++day;
			}
		// day is now date of 3rd Sunday
		}
	else if (_rule.indexOf("last") > -1)
		{
		day = 31;
		while (1)
			{
			var date = new Date (year, month, day);
			var dow = date.getDay();
			if (dow == dayNumbers.Sun)
				break;
			--day;
			}
		// day is now date of last Sunday
		}
	return new Date (year, month, day, 0, 0, 0);
	}

function getTheHourFor (_rule)
	{
	// set the hour
	if (_rule.indexOf("1am") > -1)
		hour = 1;
	else if (_rule.indexOf("2am") > -1)
		hour = 2;
	else if (_rule.indexOf("3am") > -1)
		hour = 3;
	else if (_rule.indexOf("4am") > -1)
		hour = 4;
	return hour;
	}

function isDSTFor (_city)
	{
	var offset = _city.offset;
	var now = new Date ();
	var utcYear = now.getUTCFullYear();
	var utcMonth = now.getUTCMonth();
	var utcDate = now.getUTCDate();
	var utcHours = now.getUTCHours();
	var dateInCity = new Date (new Date (utcYear, utcMonth, utcDate, utcHours, 0, 0).getTime() + offset * 60 * 60 * 1000);
	var cityStartDate = new Date (_city.dstStart.getTime() + _city.dstStartHour * 3600000);
	var cityEndDate = new Date (_city.dstEnd.getTime() + _city.dstEndHour * 3600000);
	var sum1 = (dateInCity > cityStartDate && dateInCity < cityEndDate) && !_city.dstReversed;
	var sum2 = (dateInCity < cityEndDate || dateInCity > cityStartDate) && _city.dstReversed;
	var result = _city.isDST = (sum1 || sum2) ? true : false;
	_city.localDate = _city.isDST ? (new Date (dateInCity.getTime() + 3600000)) : dateInCity;
	_city.isAM = _city.localDate.getHours() < 12 ? true : false;
	return result;
	}

var numClocks = 0;

function ClockCity (_name, _hoursFromUT, _DST_startDate, _DST_endDate, _dstReversed)
	{
	this.name = _name;
	this.offset = _hoursFromUT;
	this.dstObserved = (_DST_startDate && _DST_startDate > "") ? true : false;
	this.dstStart = getTheDateFor(_DST_startDate);
	this.dstStartHour = getTheHourFor(_DST_startDate);
	this.dstEnd = getTheDateFor(_DST_endDate);
	this.dstEndHour = getTheHourFor(_DST_endDate);
	this.dstReversed = (_dstReversed) ? true : false;
	//alert(this.dstStart + "\n" + this.dstEnd);
	this.idx = numClocks++;
	cities[this.idx] = this;
	this.observing = isDSTFor(this);
	return this;
	}

var NewYork = new ClockCity ("New York", -5, "second Sunday in March at 2am", "first Sunday in November at 2am");
var London  = new ClockCity ("London",    0, "last Sunday in March at 1am",   "last Sunday in October at 1am");
var Paris   = new ClockCity ("Paris",    +1, "last Sunday in March at 1am",   "last Sunday in October at 1am");
var Baghdad = new ClockCity ("Baghdad",  +3, "April 1st at 3am",  "August 1st at 3am");
var Mumbai  = new ClockCity ("Mumbai",   +5.5, "", "");		//NO DST
var Sydney  = new ClockCity ("Sydney",  +10, "last Sunday in October at 2am", "last Sunday in March at 2am", true);

function addSuffix (_n)
	{
	switch (_n)
		{
		case 1:
			return _n + "st";
		case 2:
			return _n + "nd";
		case 3:
			return _n + "rd";
		default:
			return _n + "th";
		}
	}

function setClockTitle (_city)
	{
	var date = _city.localDate;
	document.getElementById("clockTitle"+_city.idx).title = (_city.isAM ? "AM" : "PM") + " " + (_city.isDST ? "DST" : "") + " " 
				+ dayNames[date.getDay()] + " " + addSuffix(date.getDate()) + " " + monthNames[date.getMonth()] + " " + date.getFullYear();
	}

function insertClock (_city)
	{
	var diameter = 70;
	var timezoneOffset = _city.offset + (_city.isDST ? 1 : 0);
	
	var newHTML = '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0"';
	newHTML += '		   class="clock" id="WebClock" align="middle">';
	newHTML += '	<param name="allowScriptAccess" value="sameDomain" />';
	newHTML += '	<param name="movie" value="Flash App - Web Clock - January 2007.swf?CityName=' + _city.name + '&TimeOffset=' + timezoneOffset + '" />';
	newHTML += '	<param name="quality" value="high" />';
	newHTML += '	<param name="wmode" value="transparent" />';
	newHTML += '	<param name="bgcolor" value="#ffffff" />';
	newHTML += '	<embed src="Flash App - Web Clock - January 2007.swf?CityName=' + _city.name + '&TimeOffset=' + timezoneOffset + '"';
	newHTML += '			quality="high" wmode="transparent" bgcolor="#ffffff" width="' + diameter + '" height="' + diameter + '"';
	newHTML += '			name="Flash App - Web Clock - January 2007" align="middle"';
	newHTML += '			allowScriptAccess="sameDomain" type="application/x-shockwave-flash"';
	newHTML += '			pluginspage="http://www.macromedia.com/go/getflashplayer" />';
	newHTML += '</object><br><span id="clockTitle'+_city.idx+'" title="" style="cursor:default;">' + _city.name + '</span>';

	document.getElementById("clockHolder"+_city.idx).innerHTML = newHTML;
	setClockTitle(_city);
	}

function setClockTitles ()
	{
	setClockTitle(NewYork);
	setClockTitle(London);
	setClockTitle(Paris);
	setClockTitle(Baghdad);
	setClockTitle(Mumbai);
	setClockTitle(Sydney);
	}

function insertClocks ()
	{
	insertClock(NewYork);
	insertClock(London);
	insertClock(Paris);
	insertClock(Baghdad);
	insertClock(Mumbai);
	insertClock(Sydney);
	setInterval("setClockTitles()", 1000);
	}

function showClockHelp ()
	{
	var msg = "Flash Clocks by S.Vanryckeghem and J.Conti for WriteBetterNews.com\n\n";
	msg += "  CITY\t    CURRENT\t    ZONE\t\t  DST\t  DATES\n";
	for (i = 0; i < cities.length; ++i)
		{
		msg += cities[i].name + "\t  " + getTimeForCity(cities[i]) + "\t  GMT" + (cities[i].offset > 0 ? "+" : "") + (cities[i].offset != 0 ? cities[i].offset : "");
		if (!cities[i].dstObserved)
			msg += "\t - \n";
		else
			{
			msg += "       \t" + (cities[i].observing ? "on" : "off") + "\t";
			if (cities[i].dstReversed)
				msg += "ends " + formatDateAndHour(cities[i].dstEnd,cities[i].dstEndHour) + "\tstarts " + formatDateAndHour(cities[i].dstStart,cities[i].dstStartHour) + "\n";
			else
				msg += "starts " + formatDateAndHour(cities[i].dstStart,cities[i].dstStartHour) + "\tends " + formatDateAndHour(cities[i].dstEnd,cities[i].dstEndHour) + "\n";
			}
		}
	alert(msg);
	}

// http://www.timeanddate.com/worldclock/
// http://www.timeanddate.com/time/dst2007a.html
// http://home.tiscali.nl/~t876506/TZworld.html
// http://webexhibits.org/daylightsaving/g.html

function getDateAsString (_theDate, _format)
	{
	var dateString, mm, dd, yy, dow;
	dateString = (_format && _format > "") ? _format : "www, mmm dth";

	if (!_theDate.getTime)
		_theDate = new Date (_theDate);
	var mm = parseInt(_theDate.getMonth() + 1);
	var dd = parseInt(_theDate.getDate());
	var yy = parseInt(_theDate.getFullYear());
	var dow = parseInt(_theDate.getDay());

	dateString = dateString.replace("www", dayNames[dow]);
	dateString = dateString.replace("mmm", monthNames[mm-1]);
	dateString = dateString.replace("th", dd % 10 == 1 ? "st" : (dd % 10 == 2 ? "nd" : (dd % 10 == 3 ? "rd" : "th")));
	dateString = dateString.replace("mm", (mm < 10 ? "0" : "") + mm);
	dateString = dateString.replace("m", mm);
	dateString = dateString.replace("dd", (dd < 10 ? "0" : "") + dd);
	dateString = dateString.replace("d", dd);
	dateString = dateString.replace("yyyy", yy);
	var y2d = yy % 100;
	dateString = dateString.replace("yy", (y2d < 10 ? "0" : "") + y2d);

	return dateString;
	}

function getTimeAsString (_h, _m, _s, _format)
    {
    var timeString, hh12, hh24, mm, ss, ampm;
    timeString = (_format) ? _format : "h:mm:ss aa";

    hh12 = parseInt(_h);
    ampm = (hh12 < 12) ? "am" : "pm";
    hh12 = (hh12 == 0 || hh12 == 12) ? 12 : hh12 % 12;
    hh24 = parseInt(_h);
    mm = parseInt(_m);
    ss = parseInt(_s);

    timeString = timeString.replace("hh", (hh12 < 10 ? "0" : "") + hh12);
    timeString = timeString.replace("h", hh12);
    timeString = timeString.replace("HH", (hh24 < 10 ? "0" : "") + hh24);
    timeString = timeString.replace("H", hh24);
    timeString = timeString.replace("mm", (mm < 10 ? "0" : "") + mm);
    timeString = timeString.replace("m", mm);
    timeString = timeString.replace("ss", (ss < 10 ? "0" : "") + ss);
    timeString = timeString.replace("s", ss);
    timeString = timeString.replace("aa", ampm);

    return timeString;
    }

function getHourAsString (_theHour, _format)
	{
	var timeString, hh12, hh24, mm, ss, ampm;
	timeString = (_format && _format > "") ? _format : "haa";

	var hh12 = parseInt(_theHour);
	var ampm = (hh12 < 12) ? "am" : "pm";
	var hh12 = (hh12 == 0) ? 12 : hh12 % 12;
	var hh24 = parseInt(_theHour);

	timeString = timeString.replace("hh", (hh12 < 10 ? "0" : "") + hh12);
	timeString = timeString.replace("h", hh12);
	timeString = timeString.replace("HH", (hh24 < 10 ? "0" : "") + hh24);
	timeString = timeString.replace("H", hh24);
	timeString = timeString.replace("aa", ampm);

	return timeString;
	}

function formatDateAndHour (_theDate, _theHour, _format)
    {
	var format = (_format && _format > "") ? _format : "@d @t";
    var result = new String (format);
    result = result.replace("@d", getDateAsString(_theDate));
    result = result.replace("@t", getHourAsString(_theHour));
    return result;
    }

function getTimeForCity (_city)
	{
	var now = new Date ();
	var h = now.getUTCHours();
	var m = now.getUTCMinutes();
	var s = now.getUTCSeconds();
	h = (h + parseInt(_city.offset) + (_city.isDST ? 1 : 0)) % 24;
	m = parseInt(m + (_city.offset % 1 * 60));
	var t = h * 3600 + m * 60 + s;
	h = parseInt(t / 3600);
	m = parseInt((t % 3600) / 60);
	s = parseInt(t % 60);
	return getTimeAsString(h, m, s);
	}

