/**
*
*   Silly Clock DOM Version (06/06/2011)
*
*   - A JavaScript which was originally written by Kurt Grigg in 2003.
*
* I re-wrote the whole script to make it fit modern DOM-scripting methods
* as well as an unobtrusive writing style. I also added some features...
*
* Since the script has ben re-written from scratch I therefore claim
* copyright and release it under the terms of the Lesser Gnu Public License.
*
* SOFTWARE LICENSE: LGPL
* (C) 2008 Felix Riesterer
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* 
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
* 
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*
* Felix Riesterer (Felix.Riesterer@gmx.net)
*/


var SillyClock = {
	settings : {
		lang : "en",
		faceStyle : "decimal",
		faceFont : "Arial",
		faceFontWeight : "bold",
		faceColor : "000080",
		dateFont : "Arial",
		dateFontWeight : "normal",
		dateColor : "008000",
		dateRotateSpeed : 0.06,
		dateUpdateInSeconds : true,
		secondsColor : "ff0000",
		minutesColor : "00ff00",
		hoursColor : "0000ff",
		clockSize : 3,
		clockDY : 0,
		clockDX : 10,
		clockFollowsMouse : false,
		fancyMode : true,
		speed : 0.5, // fancy mode adjusting
		prefix : "silly_clock"
	},

	langs : {
		de : {
			days : ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
			months : ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
			dateOrder : "%day, %date. %month %year "
		},

		en : {
			days : ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
			months : ["January", "February", "March", "April", "May", "June", "July", "August", "September", "Oktober", "November", "December"],
			dateOrder : "%day %date, %month %year "
		}
	},

	faceStyles : {
		decimal : "1 2 3 4 5 6 7 8 9 10 11 12",
		roman : "I II III IV V VI VII VIII IX X XI XII"
	},

	dateStr : "",

	elements : {
		/* each array will contain objects like this { elm : [HTMLObject], x : offsetLeft, y : offsetTop, dx : deltyX, dy : deltaY } */
		face : [],
		dateStr : [],
		hands : {
			seconds : [],
			minutes : [],
			hours : []
		}
	},

	pos : { left: 600, top : 170 },
	step : 1,
	lastSecond : 0,

	docBody : false,
	div : null,
	oldDocOnMouseMove : null,
	oldWinOnLoad : null,


	getDateStr : function () {
		var now = new Date(),
			date = now.getDate(),
			day = now.getDay(),
			month = now.getMonth(),
			year = now.getYear(),
			dateStr = this.langs[this.settings.lang].dateOrder;

		if (year < 2000)
			year += 1900;

		dateStr = dateStr.replace(/\%day/, this.langs[this.settings.lang].days[day]);
		dateStr = dateStr.replace(/\%month/, this.langs[this.settings.lang].months[month]);
		dateStr = dateStr.replace(/\%year/, year);
		dateStr = dateStr.replace(/\%date/, date);

		return dateStr;
	},


	delay : function () {
		var t = SillyClock, i;

		if (t.div) {
			if (t.settings.fancyMode) {
				t.elements.dateStr[0].y = Math.round(t.elements.dateStr[0].dy += (t.pos.top - t.elements.dateStr[0].dy) * t.settings.speed);
				t.elements.dateStr[0].x = Math.round(t.elements.dateStr[0].dx += (t.pos.left - t.elements.dateStr[0].dx) * t.settings.speed);

				for (i = 1; i < t.elements.dateStr.length; i++) {
					t.elements.dateStr[i].y = Math.round(t.elements.dateStr[i].dy += (t.elements.dateStr[i - 1].y - t.elements.dateStr[i].dy) * t.settings.speed);
					t.elements.dateStr[i].x = Math.round(t.elements.dateStr[i].dx += (t.elements.dateStr[i - 1].x - t.elements.dateStr[i].dx) * t.settings.speed);
				}

				t.elements.face[0].y = Math.round(t.elements.face[0].dy += (t.pos.top - t.elements.face[0].dy) * t.settings.speed);
				t.elements.face[0].x = Math.round(t.elements.face[0].dx += (t.pos.left - t.elements.face[0].dx) * t.settings.speed);

				for (i = 1; i < t.elements.face.length; i++) {
					t.elements.face[i].y = Math.round(t.elements.face[i].dy += (t.elements.face[i - 1].y - t.elements.face[i].dy) * t.settings.speed);
					t.elements.face[i].x = Math.round(t.elements.face[i].dx += (t.elements.face[i - 1].x - t.elements.face[i].dx) * t.settings.speed);
				}
			} else {
				for (i = 0; i < t.elements.dateStr.length; i++) {
					t.elements.dateStr[i].y = Math.round(t.pos.top);
					t.elements.dateStr[i].x = Math.round(t.pos.left);
				}
				for (i = 0; i < t.elements.face.length; i++) {
					t.elements.face[i].y = Math.round(t.pos.top);
					t.elements.face[i].x = Math.round(t.pos.left);
				}
			}

			t.update();
		} else {
			if (t.interval)
				t.interval = window.clearInterval(t.interval);
		}

		if (!t.interval && t.div)
			t.interval = window.setInterval(SillyClock.delay, 40);
	},


	update : function () {
		var now = new Date(),
			sec = now.getSeconds(),
			seconds = -1.57 + Math.PI * sec/30,
			minutes = -1.57 + Math.PI * now.getMinutes()/30,
			hours = -1.575 + Math.PI * now.getHours()/6 + Math.PI * parseInt(now.getMinutes())/360,
			dateStr = this.getDateStr(),
			i, part;

		if (this.dateStr != dateStr || !this.div) {
			this.setClock();
			this.update();
			return true;
		}

		this.div.style.left = this.settings.clockSize * 35 + this.settings.clockDX + "px";
		this.div.style.top = this.settings.clockSize * 35 + this.settings.clockDY + "px";

		// position clock face
		part = 2 * Math.PI / this.elements.face.length;
		for (i = 0; i < this.elements.face.length; i++) {

			this.elements.face[i].elm.style.top = Math.floor(
					this.settings.clockSize * 25 * Math.sin((i -2) * part)
				)
				+ Math.floor(this.elements.face[i].y)
				+ "px";
			this.elements.face[i].elm.style.left = Math.floor(
					this.settings.clockSize * 25 * Math.cos((i -2) * part)
				)
				+ Math.floor(this.elements.face[i].x)
				+ "px";
		}

		// position date string
		part = 2 * Math.PI / this.elements.dateStr.length;
		for (i = 0; i < this.elements.dateStr.length; i++) {
			this.elements.dateStr[i].elm.style.top = Math.floor(
					this.settings.clockSize * 35 * Math.sin(-this.step + i * part)
					+ 1 * this.settings.clockSize
				)
				+ Math.floor(this.elements.dateStr[i].y)
				+ "px";
			this.elements.dateStr[i].elm.style.left = Math.floor(
					this.settings.clockSize * 35 * Math.cos(-this.step + i * part)
					+ 2 * this.settings.clockSize
				)
				+ Math.floor(this.elements.dateStr[i].x)
				+ "px";
		}

		if ((this.settings.dateUpdateInSeconds && this.lastSecond != sec) || !this.settings.dateUpdateInSeconds) {
			this.lastSecond = sec;
			this.step += this.settings.dateRotateSpeed;
			if (this.step > 2 * Math.PI)
				this.step = 0;
		}

		// position hours hand
		for (i = 0; i < this.elements.hands.hours.length; i++){
			this.elements.hands.hours[i].elm.style.top = Math.floor(
					this.settings.clockSize * 5 * i * Math.sin(hours)
				)
				- Math.floor(1.5 * this.settings.clockSize)
				+ Math.floor(this.elements.face[i].y)
				+ "px";
			this.elements.hands.hours[i].elm.style.left = Math.floor(
					this.settings.clockSize * 5 * i * Math.cos(hours)
				)
				- Math.floor(1.5 * this.settings.clockSize)
				+ Math.floor(this.elements.face[i].x)
				+ "px";
		}

		// position minutes hand
		for (i = 0; i < this.elements.hands.minutes.length; i++){
			this.elements.hands.minutes[i].elm.style.top = Math.floor(
					this.settings.clockSize * 5 * i * Math.sin(minutes)
				)
				- Math.floor(1.5 * this.settings.clockSize)
				+ Math.floor(this.elements.face[i].y)
				+ "px";
			this.elements.hands.minutes[i].elm.style.left = Math.floor(
					this.settings.clockSize * 5 * i * Math.cos(minutes)
				)
				- Math.floor(1.5 * this.settings.clockSize)
				+ Math.floor(this.elements.face[i].x)
				+ "px";
		}

		// position seconds hand
		for (i = 0; i < this.elements.hands.seconds.length; i++){
			this.elements.hands.seconds[i].elm.style.top = Math.floor(
					this.settings.clockSize * 5 * i * Math.sin(seconds)
				)
				- Math.floor(1.5 * this.settings.clockSize)
				+ Math.floor(this.elements.face[i].y)
				+ "px";
			this.elements.hands.seconds[i].elm.style.left = Math.floor(
					this.settings.clockSize * 5 * i * Math.cos(seconds)
				)
				- Math.floor(1.5 * this.settings.clockSize)
				+ Math.floor(this.elements.face[i].x)
				+ "px";
		}

	},


	setClock : function () {
		var body = document.getElementsByTagName("body")[0],
			face, dateStr, hands, h, i, j, x, y, div, span;

		if (typeof(this.faceStyles[this.settings.faceStyle]) != "undefined") {
			face = this.faceStyles[this.settings.faceStyle];
		} else {
			face = this.faceStyles.decimal;
		}

		this.settings.clockSize = (this.settings.clockSize < 1) ? 1 : this.settings.clockSize;
		this.settings.clockSize = (this.settings.clockSize > 12) ? 12 : this.settings.clockSize;

		div = document.getElementById(this.settings.prefix);
		if (div) {
			div.parentNode.removeChild(div);
		}

		div = document.createElement("div");
		div.id = this.settings.prefix;
		div.style.position = "absolute";
		div.style.textAlign = "center";
		body.appendChild(div);
		this.div = div;

		// draw face
		face = face.split(" ");
		div = document.createElement("div");
		div.id = this.settings.prefix + "_face";
		div.style.color = "#" + this.settings.faceColor;
		div.style.fontFamily = this.settings.faceFont;
		div.style.fontWeight = this.settings.faceFontWeight;
		div.style.fontSize = (this.settings.clockSize * 6 + 4) + "px";
		this.div.appendChild(div);

		for (i = 0; i < face.length; i++) {
			span = document.createElement("span");
			this.elements.face[this.elements.face.length] = { elm : span, x : 0, y : 0, dx : 0, dy : 0 };
			span.style.position = "absolute";
			span.style.display = "block";
			span.style.width = Math.floor(this.settings.clockSize * 6 + 4) + "px";
			span.appendChild(document.createTextNode(face[i]));
			div.appendChild(span);
		}

		dateStr = this.getDateStr();
		this.dateStr = dateStr;

		// draw date string
		dateStr = dateStr.split("");
		div = document.createElement("div");
		div.id = this.settings.prefix + "_date";
		div.style.color = "#" + this.settings.dateColor;
		div.style.fontFamily = this.settings.dateFont;
		div.style.fontWeight = this.settings.dateFontWeight;
		div.style.fontSize = (this.settings.clockSize * 4 + 4) + "px";
		this.div.appendChild(div);
		for (i = 0; i < dateStr.length; i++) {
			span = document.createElement("span");
			this.elements.dateStr[this.elements.dateStr.length] = { elm : span, x : 0, y : 0, dx : 0, dy : 0 };
			span.style.position = "absolute";
			span.appendChild(document.createTextNode(dateStr[i]));
			div.appendChild(span);
		}

		hands = {
			str : "\u2022\u2022\u2022\u2022\u2022".split(""),
			hand : ["seconds","minutes","hours"]
		};

		// draw hands
		div = document.createElement("div");
		div.id = this.settings.prefix + "_hands";
		div.style.fontFamily = "Arial";
		div.style.fontSize = (this.settings.clockSize * 8 + 8) + "px";
		this.div.appendChild(div);
		for (h = 0; h < hands.hand.length; h++) {
			for (i = 0; i < 5 - h; i++) {
				span = document.createElement("span");
				this.elements.hands[hands.hand[h]][this.elements.hands[hands.hand[h]].length] = { elm : span, x : 0, y : 0, dx : 0, dy : 0 };
				span.style.position = "absolute";
				span.style.display = "block";
				span.style.width = (this.settings.clockSize * 8 + 8) + "px";
				span.style.color = "#" + this.settings[hands.hand[h] + "Color"];
				span.appendChild(document.createTextNode(hands.str[i]));
				div.appendChild(span);
			}
		}
	},


	move : function (e) {
		if (!e)
			e = window.event;

		if (!SillyClock.settings.clockFollowsMouse)
			return true;

		SillyClock.pos = {
			left : e.clientX,
			top : e.clientY
		};

		SillyClock.docBody = (window.document.compatMode && window.document.compatMode == "CSS1Compat") ?
			window.document.documentElement : window.document.body || null;

		SillyClock.pos.left += SillyClock.docBody.scrollLeft;
		SillyClock.pos.top += SillyClock.docBody.scrollTop;

	},


	kill : function () {
		document.onmousemove = this.oldDocOnMouseMove;
		this.elements = { face : [], dateStr : [], hands : { seconds : [], minutes : [], hours : [] }};
		if (this.div)
			this.div.parentNode.removeChild(this.div);
		this.div = null;
	},


	start : function () {
		this.elements = { face : [], dateStr : [], hands : { seconds : [], minutes : [], hours : [] }};

		SillyClock.docBody = (window.document.compatMode && window.document.compatMode == "CSS1Compat") ?
			window.document.documentElement : window.document.body || null;

		if (!this.div) {
			// re-route mousemove event handler
			SillyClock.oldDocOnMouseMove = document.onmousemove;
			document.onmousemove = function (e) {
				if (typeof(SillyClock.oldDocOnMouseMove) == "function")
					SillyClock.oldDocOnMouseMove(e);
				SillyClock.move(e);
			}
		}

		SillyClock.setClock();
		SillyClock.update();
		SillyClock.delay();

	},


	init : function () {
		// initialize when document has finished loading
		this.oldWinOnLoad = window.onload;
		window.onload = function () {
			if (typeof(SillyClock.oldWinOnLoad) == "function")
				SillyClock.oldWinOnLoad();

			SillyClock.start();
		}
	}
};

SillyClock.init();

