/*
 * Flickr Asciified - JavaScript generated ASCII art from Flickr images
 * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com
 * MIT License [http://www.opensource.org/licenses/mit-license.php]
 */


var __FlickrCallbacks = {};

var Flickr = (function() {
	var callCount = 0;
	var apiKey = "";

	function sendRequest(method, content, callback) {
		callCount++;

		var url = "http://www.flickr.com/services/rest/"
			+ "?method=" + method
			+ "&format=json"
			+ "&api_key=" + apiKey
			+ "&jsoncallback=__FlickrCallbacks.fn_" + callCount
			+ "&time=" + new Date().getTime();

		if (content) {
			for (var a in content) {
				if (content.hasOwnProperty(a)) {
					url += "&" + a + "=" + encodeURIComponent(content[a]);
				}
			}
		}
		var script = document.createElement("script");

		__FlickrCallbacks["fn_" + callCount] = 
			function(res) {
				document.body.removeChild(script);
				if (callback)
					callback(res);
			};

		script.setAttribute("type", "text/javascript");
		document.body.appendChild(script);
		script.src = url;
	}

	return {

		setAPIKey : function(key) {
			apiKey = key;
		},

		callMethod : function(method, content, callback) {
			sendRequest(method, content, callback);
		}
	}

})();


var Ascii = (function() {

	var defaultCharList = (" .,:;i1tfLCG08@").split("");
	var defaultColorCharList = (" CGO08@").split("");
	var defaultColorCharListBG = ("CGO08@").split("");

	var font = "courier new";

	// convert img element to ascii
	function asciifyImage(img, canvasImg, useColor, useBlocks, useBackground, invert, scale, resolution, charList) 
	{
		var canvas = document.createElement("canvas");
		if (!canvas.getContext) {
			return;
		}
		var ctx = canvas.getContext("2d");
		if (!ctx.getImageData) {
			return;
		}

		scale = scale || 1;
		resolution = resolution || "medium";

		charList = defaultCharList;
		if (useColor) {
			if (!useBlocks) {
				charList = defaultColorCharList;
				if (useBackground) {
					charList = defaultColorCharListBG;
				}
			}
		}

		var pixResolution = 0.5;
		switch (resolution) {
			case "low" : 	pixResolution = 0.25; break;
			case "medium" : pixResolution = 0.5; break;
			case "high" : 	pixResolution = 1; break;
		}

		var w = Math.round(parseInt(img.offsetWidth) * pixResolution);
		var h = Math.round(parseInt(img.offsetHeight) * pixResolution);

		if (useBackground && !useBlocks) {
			var bgCanvas = document.createElement("canvas");
			bgCanvas.width = bgCanvas.height = 1;
			var bgCtx = bgCanvas.getContext("2d");
			bgCtx.drawImage(img, 0, 0, w, h, 0, 0, 1, 1);
			var bgColor = bgCtx.getImageData(0,0,1,1).data;
			var bgr = bgColor[0];
			var bgg = bgColor[1];
			var bgb = bgColor[2];
		}


		canvas.width = w;
		canvas.height = h;
		canvas.style.display = "none";
		canvas.style.width = w+"px";
		canvas.style.height = h+"px";

		ctx.drawImage(img, 0, 0, w, h);
		var data = ctx.getImageData(0, 0, w, h).data;
	
		var chars = "";

		for (var y=0;y<h;y+=2) {
			for (var x=0;x<w;x++) {
				var offset = (y*w + x) * 4;
	
				var r = data[offset];
				var g = data[offset + 1];
				var b = data[offset + 2];

				var brightness = (0.3*r + 0.59*g + 0.11*b) / 255;
				var charIdx = (charList.length-1) - Math.round(brightness * (charList.length-1));

				if (invert) {
					charIdx = (charList.length-1) - charIdx;
				}

				var thisChar = charList[charIdx];

				if (thisChar == " ") 
					thisChar = "&nbsp;";

				if (useColor) {
					chars += "<span style='"
						+ "color:rgb("+r+","+g+","+b+");"
						+ (useBlocks ? "background-color:rgb("+r+","+g+","+b+");" : "")
						+ "'>" + thisChar + "</span>";
				} else {
					chars += thisChar;
				}
			}
			chars += "<br/>";
		}
	
	
		var fontSize = (2/pixResolution)*scale;
		var lineHeight = (2/pixResolution)*scale;

		// adjust letter-spacing for all combinations of scale and resolution to get it to fit the image width.
		var letterSpacing = 0;
		if (resolution == "low") {
			switch (scale) {
				case 1 : letterSpacing = -1; break;
				case 2 : 
				case 3 : letterSpacing = -2.1; break;
				case 4 : letterSpacing = -3.1; break;
				case 5 : letterSpacing = -4.15; break;
			}
		}
		if (resolution == "medium") {
			switch (scale) {
				case 1 : letterSpacing = 0; break;
				case 2 : letterSpacing = -1; break;
				case 3 : letterSpacing = -1.04; break;
				case 4 : 
				case 5 : letterSpacing = -2.1; break;
			}
		}
		if (resolution == "high") {
			switch (scale) {
				case 1 : 
				case 2 : letterSpacing = 0; break;
				case 3 : 
				case 4 : 
				case 5 : letterSpacing = -1; break;
			}
		}

		var output = document.createElement("span");
		output.innerHTML = chars;

		if (useBackground && !useBlocks) {
			output.style.backgroundColor = "rgb("+bgr+","+bgg+","+bgb+")";
		}

		var style = output.style;
		style.display = "inline";
		style.width = Math.round(w/pixResolution*scale) + "px";
		style.height = Math.round(h/pixResolution*scale) + "px";
		style.whiteSpace = "pre";
		style.margin = "0px";
		style.padding = "0px";
		style.letterSpacing = letterSpacing + "px";
		style.fontFamily = font;
		style.fontSize = fontSize + "px";
		style.lineHeight = lineHeight + "px";
		style.textAlign = "left";
		style.textDecoration = "none";

		return output;
	}

	function asciifyImageLoad(img, callback, useColor, useBlocks, useBackground, invert, scale, resolution, charList)
	{
		var canvasImg = new Image();

		var output = asciifyImage(img, canvasImg, useColor, useBlocks, useBackground, invert, scale, resolution, charList);
		if (callback) 
			callback(output);
	}

	return {
		asciify : asciifyImageLoad
	}
	
})();


(function() {

	var page = 1;
	var numPages = 0;

	var imageQueue = [];
	var $ = function(id) {return document.getElementById(id);};
	
	function onPhotosFound(res) {
		var mainContainer = $("asciiImages");
		mainContainer.innerHTML = "";

		var photos = res.photos.photo;

		numPages = res.photos.pages;

		if (photos.length > 0) {
			if (page > 1) {
				mainContainer.innerHTML += "<input type='button' value='Previous page' id='previousButton' disabled=true />";
			}
			mainContainer.innerHTML += "<input type='button' value='Reload page' id='reloadButton' disabled=true />";
			if (page < numPages) {
				mainContainer.innerHTML += "<input type='button' value='Next page' id='nextButton' disabled=true />";
			}

		}

		imageQueue = [];
		for (var i=0;i<photos.length;i++) {
			var photo = photos[i];
			var url = "http://farm" + photo.farm + ".static.flickr.com/" + photo.server + "/" + photo.id + "_" + photo.secret + "_t.jpg";
			var img = new Image();
			img.style.position = "absolute";
			img.style.left = "-10000px";

			imageQueue.push(img);
			document.body.appendChild(img);
	
			(function() {
	
			var photoDesc = photo;
	
			img.onload = function() {
	
				// (img, callback, useColor, useBlocks, useBackground, invert, scale, resolution, charList)

				try {	
				Ascii.asciify(this, 
					function(output) {
						var container = document.createElement("div");
						container.style.fontFamily = output.style.fontFamily;
						container.style.fontSize = "14px";
						container.style.margin = "10px 10px 30px 10px";
	
						var ownerUrl = "http://www.flickr.com/photos/" + photoDesc.owner + "/";
						var photoUrl = ownerUrl + photoDesc.id + "/"
	
						var byLine = document.createElement("span");
						byLine.innerHTML = "<a href=\"" + photoUrl + "\" target=\"_blank\" class=\"flickasciibylink\">\"" + photoDesc.title + "\"</a> by <a href=\"" + ownerUrl + "\" target=\"_blank\" class=\"flickasciibylink\">" + photoDesc.ownername + "</a>";
	
						container.appendChild(output);
						container.appendChild(byLine);
	
						mainContainer.appendChild(container);
						
					},
					$("colorsCheck").checked, $("blocksCheck").checked, $("autobgCheck").checked, false, 4, "high"
				);
				} catch(e) {}
	
				document.body.removeChild(this);
	
				var newQueue = [];
				for (var a=0;a<imageQueue.length;a++) {
					if (imageQueue[a] != this) 
						newQueue.push(imageQueue[a]);
				}
				imageQueue = newQueue;
				if (imageQueue.length == 0) {
					$("loadingText").innerHTML = "&nbsp;";

					if ($("nextButton")) {
						$("nextButton").disabled = false;
						$("nextButton").onclick = function() {
							page++;
							loadImages();
						};
					}

					if ($("previousButton")) {
						$("previousButton").disabled = false;
						$("previousButton").onclick = function() {
							page--;
							loadImages();
						};
					}

					if ($("reloadButton")) {
						$("reloadButton").disabled = false;
						$("reloadButton").onclick = function() {
							loadImages();
						};
					}

					$("goButton").disabled = false;
				}
	
			}
	
			})();
	
			img.src = "flickrproxy.php?url=" + encodeURIComponent(url);
		}
	}
	

	function loadImages(query) {
		query = query || lastQuery;
		$("loadingText").innerHTML = "Loading...";

		$("goButton").disabled = true;

		Flickr.callMethod(
			"flickr.photos.search", 
			{
				text : query,
				extras : "owner_name,license",
				sort : "relevance",
				per_page : 5,
				media : "photos",
				license : ($("ccOnly").checked ? "4,2,1,5" : ""),
				page : page
			}, 
			onPhotosFound
		);
		lastQuery = query;
	}
	function init() {
	
		$("goButton").onclick = function() {
			var query = $("queryInput").value.replace(/^\s+|\s+$/g, "");
			if (query == "") return;

			page = 1;

			loadImages(query);
		}
	}
	
	Flickr.setAPIKey("15dcd0ac28ab119346a34aaac1aea50a");

	window.onload = init;
	
})();
