/******************************************************************************
	tcbp.js	TweetClock Blog Parts
		$Id: tcbp.js,v 1.6 2009/11/25 23:10:48 kei Exp $
******************************************************************************/

if ((typeof(com) === 'undefined') || (! com)) {
	com = {};
}
if ((typeof(com.nantoka) === 'undefined') || (! com.nantoka)) {
	com.nantoka = {};
}

(function() {
	com.nantoka.tweetClockBlogParts = function() {
		this.elmTweetClock = null;
		this.elmTargetId = '';
		this.widthArea = 140;
		this.heightArea = 180;
		this.posX = 0;
		this.posY = 0;
		this.sizeNumber24 = 10;
		this.sizeCenter = 24;
		this.radNumber24 = 50;
		this.radHistgram = 65;
		this.sizeHistgram = 24;
		this.sizeHourHands = 48;
		this.sizeMinHands = 24;
		this.sizeSecHands = 96;
		this.radHourHands = 48;
		this.radMinHands = 64;
		this.radSecHands = 72;
		this.sizeLoading = 64;

		this.colorTitleFg = '#ffffff';
		this.colorTitleBg = '#3082af';
		this.colorClockFg = '#000000';
		this.colorClockBg = '#ffffff';
		this.colorGraphBg = '#ffffff';
		this.colorGraphFg = '#ff0000';

		this.colHistgramFg = [ 255, 0, 0 ];
		this.colHistgramBg = [ 255, 248, 220 ];
		this.isSecDisp = false;
		this.isRound = false;
		this.isNoTitle = false;
		this.elmHourHands = [];
		this.elmMinHands = [];
		this.elmSecHands = [];
		this.elmHistgram= [];
		this.elmLoading = null;
		this.elmTimeZone = null;

		this.utcOffset = 0;
		this.arrayTimeLine = null;

		this.countTweet = 20;

		this.init.apply(this, arguments);
	};

com.nantoka.tweetClockBlogParts.prototype = {

	init: function(arg) {
		if (arg.id) {
			this.elmTweetClock = document.getElementById(arg.id);
		}
		if (arg.width > this.widthArea) {
			this.widthArea = parseInt(arg.width, 10);
		}
		if (arg.height > this.heightArea) {
			this.heightArea = parseInt(arg.height, 10);
		}
		if (arg.isSec) {
			this.isSecDisp = true;
		}
		if (arg.tweetNum) {
			this.countTweet = parseInt(arg.TweetNum, 10);
		}
		this.elmTargetId = arg.id.replace(/^[a-zA-Z0-9\-_]g/, '');

		if (arg.theme.background) {
			this.colorTitleFg = this.colorClockBg = arg.theme.background;
		}
		if (arg.theme.titleframe) {
			this.colorTitleBg = arg.theme.titleframe;
		}
		if (arg.theme.text) {
			this.colorClockFg = arg.theme.text;
		}
		if (arg.theme.histgram) {
			this.colorGraphFg = arg.theme.histgram;
			this.colHistgramFg = this.hexColorToArray(arg.theme.histgram, this.colHistgramFg);
		}
		if (arg.theme.histgrambg) {
			this.colorGraphBg = arg.theme.histgrambg;
			this.colHistgramBg = this.hexColorToArray(arg.theme.histgrambg, this.colHistgramBg);
		}
		if (arg.theme.isRound) {
			this.isRound = arg.theme.isRound;
		}
		if (arg.theme.NoTitle) {
			this.isNoTitle = arg.theme.NoTitle;
		}

		return true;
	},

	hexColorToArray: function(color, def) {
		if ((color.length != 7) || (color.charAt(0) != '#')) {
			return def;
		}
		var arr = [];
		arr[0] = parseInt(color.substr(1,2), 16);
		arr[1] = parseInt(color.substr(3,2), 16);
		arr[2] = parseInt(color.substr(5,2), 16);
		return arr;
	},

	loadError: function() {
		if (this.elmLoading) {
			var e = this.elmLoading;
			e.innerHTML = 'Load Error'
			e.style.zIndex = 2000;
		}
	},

	loadComplete: function() {
		if (this.elmLoading) {
			var e = this.elmLoading;
			e.style.display = 'none';
		}
	},

	drawWidget: function(name) {
		if (this.elmTweetClock) {
			var eTc = this.elmTweetClock;
			eTc.style.width = this.widthArea + 'px';
			eTc.style.height = this.heightArea + 'px';
			eTc.style.lineHeight = 1.0;
			eTc.style.margin = '0px';
			eTc.style.clear = 'both';

			var titleHeight = 0;
			if (! this.isNoTitle) {
				var e = document.createElement('div');
				e.style.width = (this.widthArea - 20) + 'px';
				e.style.fontSize = '14px';
				titleHeight = 14*2 + 10;
				e.style.fontFamily = '"lucida grande",lucida,tahoma,helvetica,arial,sans-serif';
				e.style.fontWeight = 'bold';
				e.style.height = titleHeight + 'px';
				e.style.backgroundColor = this.colorTitleBg;
				e.style.color = this.colorTitleFg;
				e.style.padding = '5px 10px 5px 10px';
				e.style.margin = '0px';
				if (this.isRound) {
					e.style.borderRadius = '10px 10px 0px 0px';
					e.style.MozBorderRadius = '10px 10px 0px 0px';
					e.style.WebkitBorderRadius = '10px 10px 0px 0px';
				}
				e.innerHTML = '<a href="http://tc.nantoka.com/' + name + '" target="_blank"'
					+ ' style="text-decoration:none !important; color: ' + this.colorTitleFg + ';">'
					+ name + "'s<br>TweetClock</a>";
				e.onmouseover = function() {this.style.textDecoration = 'underline'; };
				e.onmouseout = function() {this.style.textDecoration = 'none'; };
				eTc.appendChild(e);
			}

			var e = document.createElement('div');
			e.style.width = (this.widthArea - 2) + 'px';
			e.style.height = (this.heightArea - (titleHeight + 10 + 1)) + 'px';
			e.style.backgroundColor = this.colorClockBg;
			e.style.color = this.colorClockFg;
			e.style.borderStyle = 'none solid solid solid';
			e.style.borderWidth = '1px';
			e.style.borderColor = this.colorTitleBg;
			e.style.margin = '0px';
			if (this.isRound) {
				e.style.borderRadius = '0px 0px 10px 10px';
				e.style.MozBorderRadius = '0px 0px 10px 10px';
				e.style.WebkitBorderRadius = '0px 0px 10px 10px';
			}
			e.style.position = 'relative';
			e.style.textAlign = 'center';
			eTc.appendChild(e);

			this.posX = (this.widthArea - 2) / 2;
			this.posY = (this.heightArea - (titleHeight + 10 + 1) - 20) / 2;

			var rmax;
			if (this.posX < this.posY) {
				rmax = this.posX - 1;
			}
			else {
				rmax = this.posY - 1;
			}

			this.sizeNumber24 = rmax / 7;
			this.sizeCenter = rmax / 2
			this.sizeHistgram = rmax / 4;
			this.radHistgram = rmax - this.sizeHistgram / 4;
			this.radNumber24 = rmax - this.sizeNumber24 - this.sizeHistgram / 4 - 2;

			this.sizeHourHands = rmax / 4;
			this.sizeMinHands = rmax / 6;
			this.sizeSecHands = rmax / 8;
			this.radHourHands = this.radNumber24 * 0.6;
			this.radMinHands = this.radNumber24 * 0.8;
			this.radSecHands = this.radNumber24 * 0.85;

			this.sizeLoading = rmax / 2.5;

			this.drawClockFace(e);
			this.drawClockHands(e);
		}
	},

	drawClockFace: function(eface) {
		// Center dot
		var e = document.createElement('div');
		e.innerHTML = '&#x25cf;';
		e.style.zIndex = 100;
		e.style.fontFamily = "'Courier New', monospace";
		e.style.fontSize = this.sizeCenter + 'px';
		e.style.width = this.sizeCenter + 'px';
		e.style.margin = '0px';
		e.style.position = 'absolute';
		e.style.top = (this.posY - this.sizeCenter / 2) + 'px';
		e.style.left = (this.posX - this.sizeCenter / 2) + 'px';
		e.style.background = 'transparent none';
		eface.appendChild(e);

		// TimeZone
		var e = this.elmTimeZone = document.createElement('div');
		e.innerHTML = '';
		e.style.zIndex = 100;
		e.style.fontFamily = 'arial, sans-serif';
		//e.style.fontStyle = 'italic';
		e.style.fontSize = this.sizeNumber24 + 'px';
		e.style.fontFamily = "'Impact', sans-serif";
		e.style.margin = '0px';
		e.style.position = 'absolute';
		e.style.bottom = '5px';
		e.style.right = '10px';
		e.style.textAlign = 'right';
		e.style.background = 'transparent none';
		eface.appendChild(e);

		// numbers 24
		for (var i = 0; i < 24; i++) {
			var x = this.posX + Math.cos((2 * Math.PI / 24 * i) - Math.PI / 2) * this.radNumber24;
			var y = this.posY + Math.sin((2 * Math.PI / 24 * i) - Math.PI / 2) * this.radNumber24;
			var e = document.createElement('div');
			e.innerHTML = i ? i : 24;
			e.style.zIndex = 100;
			e.style.fontSize = this.sizeNumber24 + 'px';
			e.style.width = (this.sizeNumber24 * 2) + 'px';
			e.style.margin = '0px';
			e.style.fontFamily = "'Impact', sans-serif";
			e.style.position = 'absolute';
			e.style.top = (y - this.sizeNumber24 / 2) + 'px';
			e.style.left = (x - this.sizeNumber24) + 'px';
			e.style.background = 'transparent none';
			eface.appendChild(e);
		}

		// histgram
		for (var i = 0; i < 48; i++) {
			var x = this.posX + Math.cos((2 * Math.PI / 48 * i) - Math.PI / 2) * this.radHistgram;
			var y = this.posY + Math.sin((2 * Math.PI / 48 * i) - Math.PI / 2) * this.radHistgram;
			var e = this.elmHistgram[i] = document.createElement('div');
			e.innerHTML = '&#x25cf;';
			e.style.zIndex = 100;
			e.style.color = 'rgb(' + this.colHistgramBg[0] + ',' + this.colHistgramBg[1] + ',' + this.colHistgramBg[2] + ')';
			e.style.fontFamily = "'Courier New', monospace";
			e.style.fontSize = this.sizeHistgram + 'px';
			e.style.width = this.sizeHistgram + 'px';
			e.style.margin = '0px';
			e.style.position = 'absolute';
			e.style.top = (y - this.sizeHistgram / 2) + 'px';
			e.style.left = (x - this.sizeHistgram / 2) + 'px';
			e.style.background = 'transparent none';
			eface.appendChild(e);
		}

		// loading
		var e = this.elmLoading = document.createElement('div');
		e.innerHTML = 'Loading...'
		e.style.zIndex = 2000;
		e.style.color = this.colorGraphFg;
		e.style.fontSize = this.sizeLoading + 'px';
		e.style.width = (this.posX * 2) + 'px';
		e.style.margin = '0px';
		e.style.fontFamily = "'Impact', sans-serif";
		e.style.position = 'absolute';
		e.style.top = (this.posY - this.sizeLoading / 2) + 'px';
		e.style.left = '0px';
		e.style.background = 'transparent none';
		eface.appendChild(e);

		return true;
	},

	getUserTimeline: function(name) {
		var self = this;
		if (! this.elmTargetId) {
			return false;
		}
		var cbfunc = '_cbUserTimeline_' + this.elmTargetId.replace(/[^a-zA-z0-9]/g, '');
		com.nantoka.tweetClockBlogParts[cbfunc] = function(j) { self.cbUserTimeline(j); };
		var e = document.createElement("script");
		e.setAttribute("type", "text/javascript");
		e.setAttribute("src", "http://twitter.com/statuses/user_timeline.json?callback=com.nantoka.tweetClockBlogParts." + cbfunc + "&count=" + this.countTweet + "&screen_name=" + name);
		e.onerror = function(e){
			self.loadError();
		};
		document.getElementsByTagName("head").item(0).appendChild(e);
		return true;
	},

	drawClockHands: function(eface) {
		for (var i = 0; i < 3; i++) {
			var e = this.elmHourHands[i] = document.createElement('div');
			e.innerHTML = '&#x25cf;';
			e.style.zIndex = 60;
			e.style.fontFamily = "'Courier New', monospace";
			e.style.fontSize = this.sizeHourHands + 'px';
			e.style.width = this.sizeHourHands + 'px';
			e.style.margin = '0px';
			e.style.position = 'absolute';
			e.style.top = (this.posY - this.sizeHourHands / 2) + 'px';
			e.style.left = (this.posX - this.sizeHourHands / 2) + 'px';
			e.style.background = 'transparent none';
			eface.appendChild(e);
		}
		for (var i = 0; i < 4; i++) {
			var e = this.elmMinHands[i] = document.createElement('div');
			e.innerHTML = '&#x25cf;';
			e.style.zIndex = 70;
			e.style.fontFamily = "'Courier New', monospace";
			e.style.fontSize = this.sizeMinHands + 'px';
			e.style.width = this.sizeMinHands + 'px';
			e.style.margin = '0px';
			e.style.position = 'absolute';
			e.style.top = (this.posY - this.sizeMinHands / 2) + 'px';
			e.style.left = (this.posX - this.sizeMinHands / 2) + 'px';
			e.style.background = 'transparent none';
			eface.appendChild(e);
		}
		if (this.isSecDisp) {
			for (var i = 0; i < 1; i++) {
				var e = this.elmSecHands[i] = document.createElement('div');
				e.innerHTML = '&#x25cf;';
				e.style.zIndex = 30;
				e.style.fontFamily = "'Courier New', monospace";
				e.style.fontSize = this.sizeSecHands + 'px';
				e.style.width = this.sizeSecHands + 'px';
				e.style.margin = '0px';
				e.style.position = 'absolute';
				e.style.top = (this.posY - this.sizeSecHands / 2) + 'px';
				e.style.left = (this.posX - this.sizeSecHands / 2) + 'px';
				e.style.background = 'transparent none';
				eface.appendChild(e);
			}
		}
		return true;
	},

	moveClockHands: function() {
		var d = new Date();
		var ss = (d.getUTCHours() + 24) * 3600 + d.getUTCMinutes() * 60 + d.getUTCSeconds() + this.utcOffset;
		var h = (ss / 3600) % 24;
		var m = (ss / 60) % 60;
		var s = ss % 60;
		var elmHourHands = this.elmHourHands;
		var elmMinHands = this.elmMinHands;
		var elmSecHands = this.elmSecHands;
		for (var i = 0; i < elmHourHands.length; i++) {
			var r = this.radHourHands - (this.radHourHands / elmHourHands.length * i);
			var x = this.posX + Math.cos((2 * Math.PI / 24 * h) - Math.PI / 2) * r;
			var y = this.posY + Math.sin((2 * Math.PI / 24 * h) - Math.PI / 2) * r;
			elmHourHands[i].style.top = (y - this.sizeHourHands / 2) + 'px';
			elmHourHands[i].style.left = (x - this.sizeHourHands / 2) + 'px';
		}
		for (var i = 0; i < elmMinHands.length; i++) {
			var r = this.radMinHands - (this.radMinHands / elmMinHands.length * i);
			var x = this.posX + Math.cos((2 * Math.PI / 60 * m) - Math.PI / 2) * r;
			var y = this.posY + Math.sin((2 * Math.PI / 60 * m) - Math.PI / 2) * r;
			elmMinHands[i].style.top = (y - this.sizeMinHands / 2) + 'px';
			elmMinHands[i].style.left = (x - this.sizeMinHands / 2) + 'px';
		}
		if (this.isSecDisp) {
			for (var i = 0; i < elmSecHands.length; i++) {
				var r = this.radSecHands - (this.radSecHands / elmSecHands.length * i);
				var x = this.posX + Math.cos((2 * Math.PI / 60 * s) - Math.PI / 2) * r;
				var y = this.posY + Math.sin((2 * Math.PI / 60 * s) - Math.PI / 2) * r;
				elmSecHands[i].style.top = (y - this.sizeSecHands / 2) + 'px';
				elmSecHands[i].style.left = (x - this.sizeSecHands / 2) + 'px';
			}
		}
		var self = this;
		if (this.isSecDisp) {
			this.moveClockHandsTimerId = setTimeout(function(){self.moveClockHands();}, 250);
		}
		else {
			this.moveClockHandsTimerId = setTimeout(function(){self.moveClockHands();}, 15 * 1000);
		}
		return true;
	},

	updateHistgram: function(arr, d) {
		var n = arr.length;
		d = (d * arr.length) / (24 * 60 * 60);
		var i = ~~(d);
		var f = d - i;
		arr[i % n] += 1 - f;
		arr[(i + 1) % n] += f;
		return;
	},

	dispUserTimeLine: function() {
		if (this.arrayTimeLine.length) {
			var arrayTimeLine = this.arrayTimeLine;
			var now = new Date();
			var rgb = [];
			var hgram = new Array(this.elmHistgram.length);
			for (var i = 0; i < hgram.length; i++) {
				hgram[i] = 0.0;
			}
			var arr = arrayTimeLine[0].created_at.split(" ");
			var ep_last = Date.parse(arr[1] + " " + arr[2] + ", " + arr[5] + " " + arr[3]) / 1000 - now.getTimezoneOffset() * 60;
			var ep_div = 1.0;
			if (arrayTimeLine.length > 1) {
				var arr = arrayTimeLine[arrayTimeLine.length-1].created_at.split(" ");
				var ep_start = Date.parse(arr[1] + " " + arr[2] + ", " + arr[5] + " " + arr[3]) / 1000 - now.getTimezoneOffset() * 60;
				ep_div = ep_last - ep_start
			}
			for (var i = 0; i < arrayTimeLine.length; i++) {
				var arr = arrayTimeLine[i].created_at.split(" ");
				var ep = Date.parse(arr[1] + " " + arr[2] + ", " + arr[5] + " " + arr[3]) / 1000 - now.getTimezoneOffset() * 60;
				var df = now.getTime() / 1000 - ep;
				var r = this.radTweet + (this.radTweetMax - this.radTweet) * (ep_last - ep) / ep_div;
				var d = (ep + this.utcOffset) % (24 * 60 * 60);
				this.updateHistgram(hgram, d);
			}
			var hmax = 0.0;
			for (var i = 0; i < hgram.length; i++) {
				if (hgram[i] > hmax) {
					hmax = hgram[i];
				}
			}
			if (hmax) {
				for (var i = 0; i < hgram.length; i++) {
					for (j = 0; j < 3; j++) {
						rgb[j] = this.colHistgramBg[j] + (this.colHistgramFg[j] - this.colHistgramBg[j]) * hgram[i] / hmax;
					}
					this.elmHistgram[i].style.color = 'rgb(' + ~~(rgb[0]) + ',' + ~~(rgb[1]) + ',' + ~~(rgb[2]) + ')';
				}
			}
		}
		return true;
	},

	cbUserTimeline: function(json) {
		if ((json.error) || (! json.length)) {
			this.loadError();
			return false;
		}
		this.arrayTimeLine = json;
		this.loadComplete();

		this.utcOffset = json[0].user.utc_offset;
		this.elmTimeZone.innerHTML = json[0].user.time_zone;
		this.moveClockHands();
		this.dispUserTimeLine();
		return true;
	},

	Start: function(name) {
		this.userName = name;
		this.drawWidget(name);
		this.getUserTimeline(name);
	}
};

})();
