/hacks/Pixelfade/Pixelfade.js
/* Copyright 2011 The Dominion of Awesome
 * See COPYING for licensing information */
enyo.kind({
	name: "Pixelfade",
	kind: "Hack",
	style: "background-color: yellow; background-position: center center",
	preferences: [
		{name: "background", label: "Background", kind: "ListSelector", items: ['desktop wallpaper'].concat(colorList)}
	],
	background: 'desktop wallpaper',
	components: [
		{name: "canvas", nodeTag: "canvas", onclick: "canvasClick"},
		{name: "wallpaperService", kind: "PalmService",
		 service: 'palm://com.palm.systemservice',
		 method: 'getPreferences',
		 onSuccess: "gotWallpaper"}
	],
	create: function() {
		this.inherited(arguments);
	},
	rendered: function() {
		this.canvas = this.$.canvas.hasNode();
		this.context = this.canvas.getContext('2d');
		this.resize(window.innerWidth, window.innerHeight);
		this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);

		this.faders = [];
		for (var i = 0; i < 10; i++) {
			var img = new Image();
			img.src = "hacks/Pixelfade/pixelfade" + i + ".gif";
			this.faders.push(img);
		}
		this.preferencesChanged();
	},
	start: function() {
		this.resize(window.innerWidth, window.innerHeight);

		if (this.timer)
			clearInterval(this.timer);
		this.fade_val = 9;
		this.fade_dir = -1;
		this.fade_end = -1;
		this.timer = setInterval(this.fade_all.bind(this), 50);

		if (!this.spotTimer)
			this.spotTimer = setInterval(this.do_fade_spot.bind(this), 3000);
	},
	stop: function() {
		clearInterval(this.timer);
		this.timer = null;
		clearInterval(this.spotTimer);
		this.spotTimer = null;
		clearTimeout(this.fadeInTimer);
		this.fadeInTimer = null;
	},
	resize: function(w, h) {
		if (!this.canvas)
			return;
		this.canvas.style.width = w + 'px';
		this.canvas.style.height = h + 'px';
		this.canvas.width = w;
		this.canvas.height = h;
		this.context.fillColor = 'black';
		this.context.fillRect(0, 0, w, h);
	},
	hidden: function() {
		this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
	},
	preferencesChanged: function() {
		if (this.background == 'desktop wallpaper') {
			this.$.wallpaperService.call({
				keys: ['wallpaper'],
				subscribe: false
			});
		} else {
			this.setStyle('background-image: none; background-color: ' + this.background);
		}
	},
	canvasClick: function(inSender, inEvent) {
		clearTimeout(this.fadeInTimer);
		clearInterval(this.spotTimer);
		this.spotTimer = setInterval(this.do_fade_spot.bind(this), 3000);
		this.fader_go(inEvent.clientX, inEvent.clientY);
	},
	gotWallpaper: function(inSender, inResponse) {
		enyo.log("got background: " + JSON.stringify(inResponse));
		this.setStyle('background-image: url(' + inResponse.wallpaper.wallpaperFile + '); background-position: center center');
	},
	do_fade_spot: function() {
		var x = Math.floor(Math.random() * this.canvas.width);
		var y = Math.floor(Math.random() * this.canvas.height);
		this.fader_go(x, y);
	},
	fade_all: function() {
		this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
		if (this.fade_val == this.fade_end) {
			clearInterval(this.timer);
			this.timer = null;
			if (this.fade_dir == -1)
				this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
			else
				this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
		} else {
			for (var x = 0; x < this.canvas.width; x += 64) {
				for (var y = 0; y < this.canvas.height; y += 64) {
					this.context.drawImage(this.faders[this.fade_val], x, y);
				}
			}
		}
		this.fade_val += this.fade_dir;
	},
	fader_go: function(x, y) {
		this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
		this.fader_count = 0;
		this.time_faders(x, y);
		this.faderptr = new Array(10);
		for (var i=0; i < 10; i++)
			this.faderptr[i] = 0;
		this.t0 = (new Date()).getTime();
		this.faderRunning = true;
		clearInterval(this.timer);
		this.timer = setInterval(this.fader.bind(this), 50);
	},
	time_faders: function(xpos, ypos) {
		this.fadertimes = [];
		for (var y = 0; y < this.canvas.height; y += 64) {
			for (var x = 0; x < this.canvas.width; x += 64) {
				var xd = x - xpos;
				var yd = y - ypos;
				this.fadertimes.push({
					t: 125 - Math.sqrt(xd*xd + yd*yd) / 8,
					x: x,
					y: y
				});
			}
		}
		this.fadertimes.sort(function(a, b) { return a.t - b.t });
	},
	fader: function() {
		var tnow = (new Date()).getTime();
		var td = (tnow - this.t0) / 8.0;
		for (var i = 0; i < 10; i++) {
			while (this.faderptr[i] < this.fadertimes.length && this.fadertimes[this.faderptr[i]].t < td - i * 10) {
				var xpos = this.fadertimes[this.faderptr[i]].x;
				var ypos = this.fadertimes[this.faderptr[i]].y;
				this.context.clearRect(xpos, ypos, 64, 64);
				this.context.drawImage(this.faders[i], xpos, ypos);
				this.faderptr[i]++;
			}
		}
		if (this.faderptr[9] >= this.fadertimes.length) {
			clearTimeout(this.timer);
			this.fadeInTimer = setTimeout(function() {
				this.fade_val = 9;
				this.fade_dir = -1;
				this.fade_end = -1;
				this.timer = setInterval(this.fade_all.bind(this), 50);
			}.bind(this), 750);
		}
	}
});