/**
 * awFlickr
 * http://avoidwork.com
 *
 * @author Jason Mulligan
 * @version 1.0.beta
 */

/**
 * Attaching awFlickr constructor to the window onload event.
 */
window.onload = function()
{
	awFlickr.construct();
}

/**
 * awFlickr object with RESTful design.
 */
var awFlickr=(awFlickr)?awFlickr:function()
{
	/**
	 * cache holds the application settings, and json data.
	 */
	var cache =
	{
		image:"",
		imageRollBack:"",
		json:[],
		loaded:null,
		nav:false,
		set:"",
		sets:null
	};

	/**
	 * client contains functions and properties to build and maintain the gui.
	 */
	var client =
	{
		/**
		* Internet Explorer detection.
		*/
		ie:((document.all)&&(navigator.appVersion<8))?true:false,

		/**
		* cache() creates a timer to check if all of the nav size images have loaded before executing grid().
		*/
		cache: function()
		{
			if ((cache.loaded!=null) && (cache.loaded.total>0))
			{
				timers.cache = setInterval(function()
				{
					if (!cache.nav)
					{
						var id=cache.loaded.id;
						var loop=cache.loaded.total;
							
						for (i=1;i<=loop;i++)
						{
							cache.nav=(window["nav_"+id+"_"+i].complete)?true:false;
							if (!cache.nav)
							{
								break;
							}
						}

						if (cache.nav)
						{
							clearInterval(timers.cache);
							client.grid();
							awFlickr.image(1);
						}
					}
				}, 100);
					
				var id=cache.loaded.id;
				var loop=cache.loaded.total;

				for (i=1;i<=loop;i++) // caching nav size
				{
					window["nav_"+id+"_"+i]=new Image();
					window["nav_"+id+"_"+i].src=cache.loaded.image[i].square
				}

				for (i=1;i<=loop;i++) // caching display size
				{
					window["image_"+id+"_"+i]=new Image();
					window["image_"+id+"_"+i].src=cache.loaded.image[i].medium;
					(i==1)?awFlickr.image(i):void(0);
				}
					
				delete id;
				delete loop;
			}
		},

		/**
		 * Destroys an element if it exists.
		 */
		destroy: function(obj)
		{
			(document.getElementById(obj))?document.body.removeChild(document.getElementById(obj)):void(0);
		},

		/**
		 * Renders an image grid for user interaction.
		 */
		grid: function()
		{
			if (cache.loaded.total>0)
			{
				var id=cache.loaded.id;
				var loop=cache.loaded.total;
				var objContainer=document.getElementById("nav");
				var objTarget=document.createElement("div");
				objTarget.setAttribute("id","nav_container");

				for (i=1;i<=loop;i++)
				{
					var objNavItem=cache.loaded.image[i];

					var objImage=document.createElement("img");
					objImage.type="image";
					objImage.src=window["nav_"+id+"_"+i].src;
					objImage.setAttribute("alt",objNavItem.title);
					(objNavItem.title!="")?objImage.setAttribute("title", "View "+objNavItem.title):void(0);
					objImage.setAttribute("id","thumb_"+i);

					if (!document.all) //adding fade to everything except IE.
					{
						(client.ie)?objImage.setAttribute("style","filter:alpha(opacity=010)"):objImage.setAttribute("style","opacity:0");
						objImage.setAttribute("onload","awFlickr.effects.opacityChange('"+objImage.id+"',0,50,300);");
						objImage.setAttribute("onmouseover","awFlickr.effects.opacityChange('"+objImage.id+"',50,100,300);");
						objImage.setAttribute("onmouseout","awFlickr.effects.opacityChange('"+objImage.id+"',100,50,300);");
					}

					var objAnchor=document.createElement("a");
					objAnchor.setAttribute("onclick","awFlickr.image("+i+")");
					objAnchor.setAttribute("id","nav_"+i);
					objAnchor.appendChild(objImage);

					objTarget.appendChild(objAnchor);

					delete objAnchor;
					delete objImage;
					delete objNavItem;
				}

				client.reset(objContainer.id);

				if (!document.all) //adding fade to everything except IE.
				{
					(client.ie)?objTarget.setAttribute("style","filter:alpha(opacity=010)"):objTarget.setAttribute("style","opacity:0");
					objContainer.appendChild(objTarget);
					awFlickr.effects.opacityChange(objTarget.id,0,100,300);
				}
				else
				{
					objContainer.appendChild(objTarget);
				}

				delete objContainer;
				delete objTarget;
			}
		},

		/**
		 * Receives and caches an xmlHttp response, and executing events.
		 */
		httpGet: function(obj,xmlHttp,type)
		{
			if (xmlHttp.readyState==4)
			{
				switch(type)
				{
					case "json":
						if ((xmlHttp.status==200)&&(xmlHttp.responseText!=""))
						{
							eval("cache.json[\""+obj+"\"]="+xmlHttp.responseText+";");
							
							switch(obj)
							{
								case "config":
									eval("config=cache.json[\"config\"];");
									(config.keyboard)?document.onkeydown=awFlickr.keyCode:void(0);
									(!config.rightClick)?document.onmousedown=awFlickr.mouseCode:void(0);
									awFlickr.sets(1);
									awFlickr.set("photostream","photostream");
									break;
										
								case "sets":
									eval("cache.sets=cache.json[\"sets\"];");
									awFlickr.sets(1);
									break;
										
								default:
									eval("cache.loaded=cache.json[\""+obj+"\"];");
									client.cache();
									break;
							}
						}
						break;
							
					default:
						document.getElementById(obj).innerHTML=(xmlHttp.status==200)?xmlHttp.responseText:"A server error has occurred";
						break;
				}
			}
		},

		/**
		 * Creates an xmlHttp request for a URI.
		 */
		httpRequest: function(obj,resource,type)
		{
			var xmlHttp=false;

			if (window.XMLHttpRequest)
			{
				xmlHttp=new XMLHttpRequest();
			}
			else if (window.ActiveXObject)
			{
				try
				{
					xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
				}
				catch (e)
				{
					try
					{
						xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
					}
					catch (e) {}
				}
			}

			if (!xmlHttp)
			{
				return false;
			}

			xmlHttp.onreadystatechange = function() { client.httpGet(obj,xmlHttp,type); }
			xmlHttp.open("GET",resource,true);
			xmlHttp.send(null);

			delete xmlHttp;
		},

		/**
		 * Renders a loading (spinning) icon in a target element.
		 */
		icon: function(obj)
		{
			if (!document.getElementById(obj.id+"_loading"))
			{
				var objImage=document.createElement("img");
				objImage.type="image";
				objImage.src=window["icon"].src;
				objImage.setAttribute("id",obj.id+"_loading");
				objImage.setAttribute("alt","");
				(client.ie)?objImage.setAttribute("className","loading"):objImage.setAttribute("class","loading");
				obj.appendChild(objImage);
				delete objImage;
			}
		},		

		/**
		 * Erases the .innerHTML of a target element.
		 */
		reset: function(obj)
		{
			(document.getElementById(obj))?document.getElementById(obj).innerHTML="":void(0);
		}
	};

	/**
	 * Holds application config.
	 */
	var config = "";

	/**
	 * Exposed to the client.
	 */
	var pub =
	{
		/**
		* Caching the loading icon, and retrieving the config resource which creates the GUI.
		*/
		construct: function()
		{
			window["icon"]=new Image();
			window["icon"].src="http://farm5.static.flickr.com/4065/4474242391_d5ca519f5e_o.gif";
						
			var photostream=document.getElementById("photostream");
			(photostream)?photostream.setAttribute("onclick","awFlickr.reset()"):void(0);
			delete photostream;

			client.httpRequest("config","rest/config","json")
		},

		/**
		 * Various gui effects. This will be extended.
		 */
		effects:
		{
			opacity: function(opacity,id)
			{
				if (document.getElementById(id))
				{
					var objStyle=document.getElementById(id).style;
					objStyle.opacity=(opacity/100);
					objStyle.MozOpacity=(opacity/100);
					objStyle.KhtmlOpacity=(opacity/100);
					objStyle.filter="alpha(opacity="+opacity+")";
					delete objStyle;
				}
			},

			opacityChange: function(id,start,end,ms)
			{
				var speed = Math.round(ms/100);
				var timer = 0;

				if (start>end)
				{
					for (i=start;i>=end;i--)
					{
						setTimeout("awFlickr.effects.opacity("+i+",'"+id+"')",(timer*speed));
						timer++;
					}
				}
				else if (start<end)
				{
					for (i=start;i<=end;i++)
					{
						setTimeout("awFlickr.effects.opacity("+i+",'"+id+"')",(timer*speed));
						timer++;
					}
				}
			
				delete speed;
				delete timer;
			},

			opacityShift: function(id,ms)
			{
				(document.getElementById(id).style.opacity==0)?awFlickr.effects.opacityChange(id,0,100,ms):awFlickr.effects.opacityChange(id,100,0,ms);
			}
		},

		/**
		 * Renders various sizes of an image object in the gui.
		 */
		image: function(i,arg)
		{
			switch(arg)
			{
				case "close":
					priv.destroy("overlay");
					break;
					
				case "large":
					var objOverlay=document.createElement("div");
					objOverlay.setAttribute("id","overlay");
					(client.ie)?objOverlay.setAttribute("className","overlay"):objOverlay.setAttribute("class","overlay");
					
					var objAnchor=document.createElement("a");
					objAnchor.setAttribute("onclick","awFlickr.image("+i+",\"close\")");
					
					var objImage=document.createElement("img");
					objImage.setAttribute("id","large");
					objImage.src=(cache.loaded.image[i].large)?cache.loaded.image[i].large:cache.loaded.image[i].original;
					(client.ie)?objImage.setAttribute("className","original"):objImage.setAttribute("class","original");
					
					objAnchor.appendChild(objImage);
					objOverlay.appendChild(objAnchor);
					document.body.appendChild(objOverlay);

					awFlickr.effects.opacityChange(objOverlay.id,0,100,300);
					
					delete(objAnchor);
					delete(objImage);
					delete(objOverlay);

					break;
					
				default:
					var objTarget=document.getElementById("picture");	
					client.reset(objTarget.id);
	
					if (cache.loaded.total==0)
					{
						objTarget.innerHTML="<div class=\"error\"><h2>Connection Error</h2><h3>Images could not be loaded</h3></div>";
					}
					else
					{
						cache.image=parseInt(i);

						var imageNext=(cache.image==cache.loaded.total)?1:cache.image+1;

						if (document.getElementById("nav_"+cache.imageRollBack))
						{
							(client.ie)?document.getElementById("nav_"+cache.imageRollBack).setAttribute("className",""):document.getElementById("nav_"+cache.imageRollBack).setAttribute("class","");
						}

						cache.imageRollBack=cache.image; // Setting the rollback

						if (document.getElementById("nav_"+i))
						{
							(client.ie)?document.getElementById("nav_"+i).setAttribute("className","selected"):document.getElementById("nav_"+i).setAttribute("class","selected");
						}

						var objImage=document.createElement("img");
						objImage.type="image";
						objImage.src=window["image_"+cache.loaded.id+"_"+i].src;
						objImage.setAttribute("id","picture_"+i);
						objImage.setAttribute("alt",cache.loaded.image[i].title);

						if (!document.all)
						{
							(client.ie)?objImage.setAttribute("style","filter:alpha(opacity=010)"):objImage.setAttribute("style","opacity:0");
							objImage.setAttribute("onload","awFlickr.effects.opacityChange(\""+objImage.id+"\",0,100,300);");
						}

						var objAnchor=document.createElement("a");
						//objAnchor.setAttribute("onclick","awFlickr.image("+i+",\"original\")");
						objAnchor.setAttribute("id","anchor_"+cache.image);
						objAnchor.setAttribute("title","View large size");
						objAnchor.appendChild(objImage);		

						objTarget.appendChild(objAnchor);
						
						if (cache.loaded.image[i].comments.length>0)
						{
							var objHeader=document.createElement("h2");
							objHeader.innerHTML="Comments";
							objTarget.appendChild(objHeader);
							delete objHeader;
								
							for(x=0;x<cache.loaded.image[i].comments.length;x++)
							{
								var objComment=document.createElement("p");
								objComment.innerHTML="<strong>"+cache.loaded.image[i].comments[x].author+"</strong>: "+cache.loaded.image[i].comments[x].content;
								objTarget.appendChild(objComment);
								delete objComment;
							}
						}

						delete imageNext;
						delete objAnchor;
						delete objImage;
					}
					break;
			}
		},

		/**
		 * Allows the user to navigate the image grid via keyboard arrow keys.
		 */
		keyCode: function(e)
		{
			if (cache.loaded!=null)
			{
				var current=parseInt(cache.image);
				var next=new String("");
				var row=parseInt(config.image.row);
				var total=parseInt(cache.loaded.total);
				var keyCode=(window.event)?event.keyCode:e.keyCode;

				switch (keyCode)
				{
					case 37: // left
						next=((current-1)<1)?total:(current-1);
						break;
						
					case 38: // up
						if ((current-row)<1)
						{
							next=(total/row).toString();
							next=(next.indexOf(".")<0)?parseInt(next):parseInt(next.substring(0,next.indexOf(".")));
							next=current+(row*next);
							next=(next>total)?(next-row):next;
						}
						else
						{
							next=(current-row);
						}					
						break;
						
					case 39: // right
						next=((current+1)>total)?1:(current+1);
						break;
						
					case 40: // down
						if ((current+row)>total)
						{
							next=(total/row).toString();
							next=(next.indexOf(".")<0)?parseInt(next):parseInt(next.substring(0,next.indexOf(".")));
							next=current-(row*next);
							next=(next<1)?(next+row):next;
						}
						else
						{
							next=(current+row);
						}
						break;
				}
			
				(next!="")?awFlickr.image(next):void(0);

				delete current;
				delete next;
				delete row;
				delete total;
				delete keyCode;

				return false;
			}
		},

		/**
		 * Resets the gui.
		 */
		reset: function()
		{
			awFlickr.set("photostream","photostream");
		},

		/**
		 * Retrieves or loads an image set from local cache.
		 */
		set: function(i,x)
		{
			if (cache.set!=null)
			{
				objAnchor = document.getElementById("link_"+cache.set);
				(objAnchor)?((client.ie)?objAnchor.setAttribute("className",""):objAnchor.setAttribute("class","")):void(0);
				delete objAnchor;
			}

			objAnchor = document.getElementById("link_"+i);
			(objAnchor)?((client.ie)?objAnchor.setAttribute("className","selected"):objAnchor.setAttribute("class","selected")):void(0);
			delete objAnchor;

			cache.image="";
			cache.imageRollback="";
			cache.loaded=null;
			cache.nav=false;
			cache.set=i;

			client.reset("nav");
			client.reset("picture");

			client.icon(document.getElementById("nav"));
			client.icon(document.getElementById("picture"));
			
			var cached=false;
			
			for (var resource in cache.json)
			{
				if (resource==x)
				{
					cached=true;
					eval("cache.loaded=cache.json[\""+x+"\"];");
					client.grid();
					awFlickr.image(1);
					break;
				}
			}

			if (!cached)
			{
				(x=="photostream")?client.httpRequest("photostream","rest/photostream","json"):client.httpRequest(x,"rest/sets/"+x,"json");
			}
			
			delete objPointer;
			delete objFound;
			delete cached;
		},

		/**
		 * Renders a paginated list of sets.
		 */
		sets: function(offset)
		{
			if (cache.sets==null)
			{
				client.httpRequest("sets","rest/sets","json");
			}
			else
			{
				var x=config.sets.limit;
				var length=cache.sets.set.length;
				var start=(parseInt(offset)>0)?((parseInt(offset)-1)*x):0;
				var loop=((start+x)>length)?start+(length-start):start+x;

				var objContainer=document.getElementById("sets");		
				client.reset(objContainer.id);

				for (i=start;i<loop;i++)
				{
					try
					{
						var objSet=cache.sets.set[i];
						var objItem=document.createElement("li");

						var objAnchor=document.createElement("a");
						objAnchor.setAttribute("id","link_"+i);
						objAnchor.setAttribute("onclick","awFlickr.set("+i+",'"+objSet.id+"')");
						objAnchor.setAttribute("title","View "+objSet.title);
						(parseInt(cache.set)==i)?((client.ie)?objAnchor.setAttribute("className","selected"):objAnchor.setAttribute("class","selected")):void(0);
						objAnchor.innerHTML=objSet.title;

						objItem.appendChild(objAnchor);
						objContainer.appendChild(objItem);

						delete objAnchor;
						delete objItem;
						delete objSet;
					}
					catch(e) {}
				}

				var objItem=document.createElement("li");
				objItem.setAttribute("id","offsets");

				var objAnchor=document.createElement("a");
				objAnchor.setAttribute("id","sets_previous");
				objAnchor.innerHTML="&laquo;";
				(start>0)?objAnchor.setAttribute("onclick","awFlickr.sets("+(parseInt(offset)-1)+")"):void(0);
				(start>0)?objAnchor.setAttribute("title","View previous sets"):objAnchor.setAttribute("title","");
				objItem.appendChild(objAnchor);

				var objAnchor=document.createElement("a");
				objAnchor.setAttribute("id","sets_next");
				objAnchor.innerHTML="&raquo;";
				((start+x)<length)?objAnchor.setAttribute("onclick","awFlickr.sets("+(parseInt(offset)+1)+")"):void(0);
				((start+x)<length)?objAnchor.setAttribute("title","View next sets"):objAnchor.setAttribute("title","");
				objItem.appendChild(objAnchor);

				objContainer.appendChild(objItem);

				delete x;
				delete length;
				delete loop;
				delete start;

				delete objAnchor;			
				delete objItem;
				delete objContainer;
			}
		}
	};

	/**
	 * Holds timers.
	 */
	var timers =
	{
		cache:""
	};

	/**
	 * Exposing the pub class to the client.
	 */
	return pub;
}();
