var newdok_loading_image_url =null;
var newdok_enable_memo_printing=false;

function isBadPointer(ptr)
{
	return (ptr===null)||(ptr===undefined);
}

function isInFormField()
{
	var element = document.activeElement;
	while (!isBadPointer(element))
	{
		var tagName = element.tagName;
		if (!isBadPointer(tagName))
		{
			tagName=tagName.toLowerCase();
			if ((tagName === "input")||(tagName === "textarea")||(tagName === "select"))
			{
				return true;
			}
			else
			{
				if ((element.parentNode!==null)&&(element.parentNode!==undefined))
				{
					element=element.parentNode;
					continue;
				}
				else
				{
				}
			}
		}
		else
		{
			//alert("badTagName!");
		}
		break;
	}
	return false;
};

function newdok_jsonHandler(baseID)
{
	this.baseID = baseID;
	this.allocCounter = 0;
	this.registeredHandlers= new Array();
	this.defaultHandler = null;

	var self=this;
	
	this.allocateHandlerID=function()
	{
		var num = self.allocCounter;
		self.allocCounter++;
		var ret = "h_" + self.baseID + "_number_"+num;
		return ret;
	};
	
	this.register = function(jsonKey, handlerFunc)
	{
		self.registeredHandlers[jsonKey] = handlerFunc;
		return jsonKey;
	};
	
	this.unregister=function(jsonKey)
	{
		self.registeredHandlers[jsonKey] = null;
	};
	
	this.getHandler = function(jsonKey)
	{
		return self.registeredHandlers[jsonKey];
	};
	
	this.setDebugFunc = function(debugFunc)
	{
		self.onErrorFunc=debugFunc;
	};
	
	this.handleError=function(message)
	{
		var func = self.onErrorFunc;
		if (func!==null)
		{
			func(message);
		}
		else
		{
			//nothing to be done =/
		}
	};
	
	this.handleJSON=function(jsonKey, jsonLiteral)
	{
		var handler = self.getHandler(jsonKey);
		if ((handler === null)||(handler === undefined))
		{
			handler = self.defaultHandler;
			if (isBadPointer(handler))
			{
				self.handleError("no handler found for jsonKey: "+jsonKey);
				return false;
			}
		}
		else
		{
		}
		var ret;
		ret=handler(jsonKey, jsonLiteral);
		return ret;
	};
		
	this.setDefaultHandler=function(handlerFunc)
	{
		this.defaultHandler=handlerFunc;
	};
	
	this.request = function(jsonKey, url, requestParams)
	{
		
		var nd = document.createElement("script");
		nd.setAttribute("type", "text/javascript");
		
		var request = ""+ url + "?"+requestParams;
		if (requestParams != "")
		{
			request=request+"&";
		}
		request=request+"__JSON_KEY__="+jsonKey;
		
		nd.setAttribute("src", request);
		document.body.appendChild(nd);
	}
	
	return this;
}

var newdok_jsonHandler;

function onJSON(jsonKey, jsonLiteral)
{
	newdok_jsonHandler.handleJSON(jsonKey,jsonLiteral);
}




function newdok_filmstrip(jsonTarget, base_id, filmCellCount, theQueryString, jsonHandler)
{
	var enable_fastforward_and_rewind = false;
	//var enable_fastforward_and_rewind = true;

	this.jsonTarget = jsonTarget;
	//this.newdok_ajax_wordpress_query_string= '';
	this.query_string= theQueryString;// ///'';
	
	this.base_id = base_id;
	this.filmCellCount = filmCellCount;//NOTE: THIS WILL BE SET BY A SCRIPT THAT IS EMBEDDED LATER ON!
	//this.firstFilmCellIndex=0;//THIS SHOULD BE SET BY A SCRIPT THAT IS EMBEDDED LATER ON!
	
	this.filmcell_cache = new Array();
	
	this.totalItems=-1;
	//this.jsonHandler= null;
	this.jsonHandler= jsonHandler;
	this.jsonKey = null;
	this.offset = 0;
	this.errorFunc=null;
	var self=this;
	var myself=  this;
	
	this.setErrorHandlerFunc=function(func)
	{
		self.errorFunc=func;
	};
	
	var numOnSides = Math.floor(filmCellCount/2);
	var numLeftward =numOnSides;//0;//numOnSides;// //4;
	var numRightward =numOnSides;//2*numOnSides ;// 4;
	
	var getNode=function(byid)
	{
		var ret;
		ret= document.getElementById(byid);
		return ret;
	};
	
	var findNodeOfTypeInSubtree=function(nd_subtree, findTagType)
	{
		var node = nd_subtree;//lolj
		var tag_type = findTagType;
		if (node==null)
		{
			//debugMessage('node is null!');
			return null;//if we somehow are passed the wrong node, fail gracefully...
		}
		
		if (node.nodeType==1)//element type
		{
			var tagName = node.tagName;
			//tagName=tagName.trim();//only in firefox...?
			tagName=tagName.toLowerCase();
			//if (tagName == "img")
			if (tagName == tag_type)
			{
				//debugMessage('node: '+node);
				return node;
			}
			//else, continue on and examine node's children..
		}
		if (node.hasChildNodes())
		{
			var children;
			children = node.childNodes;
			var i, l = children.length;
			for (i=0; i<l; i++)
			{
				var child = children[i];
				if (child.nodeType==1)//element type
				{
					//if (child instanceof Element)//not in IE6
					{
						var tagName = child.tagName;
						//tagName=tagName.trim();//only in firefox...?
						tagName=tagName.toLowerCase();
						//if (tagName == "img")
						if (tagName == tag_type)
						{
							return child;
						}
						else
						{
							//var tmp = getImgFor(child);
							var tmp = findNodeOfTypeInSubtree(child, tag_type);//lol recursion fil^ls
							if (tmp != null)
							{
								return tmp;
							}
						}
					}
				}
			}
			return null;
		}
		else
		{
			//no children, so fail...
			return null;
		}
	};
	
	//calculateScaleToFit
	var calcScaleToFit=function(width, height, maxWidth, maxHeight)
	{
		if ((width==0)||(height == 0))
		{
			return 0;//nothing to do...lol!
			//maybe return 1 instead??
		}
		
		var widthCandidate = maxWidth / width;
		var heightCandidate = maxHeight / height;
		
		var heightFromWidthCandidate = height * widthCandidate;
		var widthFromHeightCandidate = width * heightCandidate;
		
		if (heightFromWidthCandidate>maxHeight)
		{
			return heightCandidate;
		}
		else if (widthFromHeightCandidate > maxWidth)
		{
			return widthCandidate;
		}
		else
		{
			//return max($widthFromHeightCandidate, $heightFromWidthCandidate);
			//return Math.max(widthCandidate, heightCandidate);
			return (widthCandidate>=heightCandidate)?widthCandidate:heightCandidate;
		}
	};
	
	var isChildOf = function(node, testChild)
	{
		if (node==null)
		{
			return false;
		}
		
		var children = node.childNodes;//();
		if (children==null)
		{
			return false;
		}
		var i, l = children.length;
		for (i=0; i<l; i++)
		{
			if (children[i]==testChild)
			{
				return true;//maybe use issamenode for paranoia!?or just check parent-ness of child...?
			}
		}
		return false;
	};
	
	

	
	var setTagAttribIfTagIsNotNull=function(tag, attrib, value)
	{//^lol unused...?
		if (tag===null)
		{
			return false;
		}
		else
		{
			tag.setAttribute(attrib, value);
			return true;
		}
	};
	
	var blank_filmcell_entry =
	{
		what: "filmstrip_entry",
		formatType: 1,
		content:
		{
			entry_index: -1,
			
			link_url: null,
			tooltip: null,
			label: null,
			
			image:
			{
				//src: null,
				source: null,
				alt:null,
				special: "clientside-blank",
				width: 0,
				height: 0
			}
		}
	};
	
	var loading_filmcell_entry = 
	{
		what: "filmstrip_entry",
		formatType: 1,
		content:
		{
			entry_index: -2,
			//bLoading: true,
			
			link_url: null,
			tooltip: "Loading...",
			label: "?????",//new
			
			image:
			{
				//src: "___loading___",
				source: null,
				alt: "Loading...",
				bMeta: true,
				special: "loading",
				width: 0,
				height: 0
			}
		}
	};
	
	var handleErrorFunc = function(message)
	{
		var func = self.errorFunc;
		if (func!==null)
		{
			func(message);
		}
		else
		{//lol
			//debugMessage(message);
			//alert(message);
			//alert(message);
			//do nothing... =/
		}
	};
	
	
	
	var verifyIsFilmstripCellEntry=function(filmcell_entry)
	{
		if (filmcell_entry==null)
		{
			handleErrorFunc("null filmcell_entry!");
			return false;
			
			/*
			info = new Array();
			info['image_url'] = null;
			info['permalink_url']=null;
			info['tooltip']='does not exist';
			info['image_width']=0;
			info['image_height']=0;
			*/
		}
		if (filmcell_entry.what !== "filmstrip_entry")
		{
			handleErrorFunc("not a filmstrip_entry: "+filmcell_entry.what+"!");
			return false;
		}
		else if (filmcell_entry.formatType!==1)
		{
			handleErrorFunc("filmstrip_entry has a formatType that is NOT 1: "+filmcell_entry.formatType+"...!");
			return false;
		}
		else if (filmcell_entry.content ===null)
		{
			handleErrorFunc("filmstrip_entry has a NULL content element!");
			return false;
		}
		
		var entry = filmcell_entry.content;
		var entryIndex= entry.entry_index;
		var image = entry.image;
		/*
		if (showEntryIndex===-1)
		{
			showEntryIndex = entryIndex;
		}
		*/
		if (image === null)
		{
			handleErrorFunc("entry has a NULL image element! entryIndex="+entryIndex);
			return false;
		}
		return true;
	};
	
	
	//function setFilmCell(cell_num, num, info)
	var updateFilmCellFunc = function(base_id, cellIndex, filmcell_entry, showEntryIndex)
	{		
		//if (!verify
		//handleErrorFunc("updating a cell #"+cellIndex);
		if (!verifyIsFilmstripCellEntry(filmcell_entry))
		{
			handleErrorFunc("not a filmcell_entry!");
			return false;
		}
		
		var entry = filmcell_entry.content;
		var entryIndex= entry.entry_index;
		var image = entry.image;
		
		if (showEntryIndex===-1)
		{
			showEntryIndex = entryIndex;
		}
		
		var imgW = image.width;
		var imgH = image.height;
		
		var scaleToSide = 60;
		var imageScalar = calcScaleToFit(imgW,imgH,scaleToSide,scaleToSide);
		
		imgW*=imageScalar;
		imgH*=imageScalar;
		
		
		var yOffset;
		yOffset	= Math.floor(0.5+ (scaleToSide - imgH )/2.0);
		
		imgW = Math.floor(0.5+imgW);
		imgH = Math.floor(0.5+imgH);
		
		var id_link 			= ""+base_id+"_filmcell_link_"+cellIndex;
		var id_tooltip 			= ""+base_id+"_filmcell_tooltip_"+cellIndex;
		var id_label 			= ""+base_id+"_filmcell_label_"+cellIndex;
		var id_image_container 	= ""+base_id+"_filmcell_imageContainer_"+cellIndex;
		var id_link_part2		= ""+base_id+"_filmcell_linkTwo_"+cellIndex;
		
		var tag_img_container 	= getNode(id_image_container);
		var tag_img 			= findNodeOfTypeInSubtree(tag_img_container, "img");
		var tag_tooltip 		= getNode(id_tooltip);
		var tag_label 			= getNode(id_label);
		var tag_link 			= getNode(id_link);
		var tag_link_part2 		= getNode(id_link_part2);
		
		var bNoImage = (image.source == null)&&(image.bMeta!==true);
		
		
		/*
		var bFail=false;
		if (tag_img_container==null)
		{
			bFail=true;
			debugMessage("tag_img_container was null; id="+id_image_container);
		}
		
		if (tag_label==null)
		{
			bFail=true;
			debugMessage("tag_label was null; id="+id_label);
		}
		
		if (tag_link==null)
		{
			bFail=true;
			debugMessage("tag_link was null; id="+id_link);
		}
		
		if (bFail)
		{
			debugMessage("failed to set filmcell due to one or more errors! cell_num="+cell_num);
			return false;
		}*/
		
		if (bNoImage)
		{
			if (tag_label!==null)
			{
				tag_label.innerHTML='';
			}
			
			//image tag:
			if (tag_img!=null)
			{
				tag_img.setAttribute('alt', "NO IMAGE!");
				
				if ((tag_img_container!==null)&&(isChildOf(tag_img_container, tag_img)))
				{
					tag_img_container.removeChild(tag_img);
				}
				else
				{
					handleErrorFunc('cell#'+cellIndex+": image_tag was not a child of img_container!");
					handleErrorFunc("tag_img="+tag_img);
					handleErrorFunc("tag_img_container="+tag_img_container);
					handleErrorFunc("tag_img.parentNode=  "+tag_img.parentNode.getAttribute('id'));
					//^lol reached in error case...!
				}
			}
			else
			{
				//debugMessage('cell#'+cell_num+": no image tag in container!");
			}
			
			//link tag:
			if (tag_link!==null)
			{
				tag_link.removeAttribute('href');
			}
			
			if (tag_link_part2!==null)
			{
				tag_link_part2.removeAttribute('href');
			}
			
			//tooltip tag:
			if (tag_tooltip!==null)
			{
				tag_tooltip.innerHTML = '';
			}
		}
		else
		{
			//image tag:
			if (tag_img == null)
			{
				tag_img=document.createElement('img');
				tag_img.setAttribute("border", "0");
				if (tag_img_container!==null)
				{
					tag_img_container.appendChild(tag_img);
				}
			}
			if (tag_img!==null)
			{
				var bSourceNotSet=true;
				if (image.bMeta)
				{
					if (image.special=="loading")
					{
						if (newdok_loading_image_url)
						{
							imgW=32;
							imgH=32;//lolz!
							yOffset	= Math.floor(0.5+ (scaleToSide - imgH )/2.0);//lolz new change/fix!
							
							tag_img.setAttribute('width', ''+imgW+'px');
							tag_img.setAttribute('height', ''+imgH+'px');
				
							tag_img.setAttribute('src', newdok_loading_image_url);//image_url);
							bSourceNotSet=false;
						}
					}
				}
				else
				{
					bSourceNotSet=true;
				}
				if (bSourceNotSet)
				{
					
					//if (tag_img.getAttribute("src")===image.source)
					{
						tag_img.setAttribute('width', ''+imgW+'px');
						tag_img.setAttribute('height', ''+imgH+'px');
						tag_img.style.width=''+imgW+'px';
						tag_img.style.height=''+imgH+'px';
						tag_img.setAttribute('src',image.source);//image_url);
					}
					bSourceNotSet=false;
				}
				tag_img.setAttribute('title', entry.tooltip);
				tag_img.style.position="relative";
				tag_img.style.top=""+yOffset+"px";
			}
			
			if (tag_label!==null)
			{
				//label tag:
				//var one_based_number = (showEntryIndex+1);//fixes off-by-one errors on the user-visible side of the page
				
				//var (showEntryIndex+1);//fixes off-by-one errors on the user-visible side of the page
				var mylabel = entry.label;
				//var_dump(
				//alert(mylabel);//lol
				if (mylabel==null)
				{
					mylabel ="";//hack
				}
				
				tag_label.innerHTML=''+mylabel;
				//+one_based_number;
				
				//tag_label.innerHTML=''+entry.label;//+one_based_number;
			}
			
			//link tag:			
			if (tag_link!==null)
			{
				tag_link.setAttribute('href', entry.link_url);
			}
			
			if (tag_link_part2!==null)
			{
				tag_link_part2.setAttribute('href', entry.link_url);
			}
			
			//tooltip tag:
			if (tag_tooltip!==null)
			{
				tag_tooltip.innerHTML = entry.tooltip;
			}
		}
		
		return true;
	};

	
	
	
	
	var cacheLookup=function(entry_index)
	{
		var eid = "n"+entry_index;
		var raw = self.filmcell_cache[eid];
		if (raw==null)
		{
			return null;
		}
		return raw;
	};
	
	var cacheInsert=function(entry_index, value)
	{
		//handleErrorFunc("recieved #"+entry_index);
		var eid = "n"+entry_index;
		self.filmcell_cache[eid]=value;
		//handleErrorFunc("content.image.source: "+value.content.image.source);//lok
	};
	
	var cacheMerge=function(results)
	{
		var i, l = results.length;
		for(i=0; i<l; i++)
		{
			var raw_entry = results[i];
			if (raw_entry.what == "metadata")
			{
				var entry = raw_entry.content;
				if (entry.option_key == "total_item_count")
				{
					self.totalItems = entry.value;
				}
			}
			else
			{
				if (!verifyIsFilmstripCellEntry(raw_entry))
				{
					handleErrorFunc("cache merge: not a filmcell_entry!");
					continue;
				}
				
				var index=raw_entry.content.entry_index;
				cacheInsert(index, raw_entry);
			}
			
			if (raw_entry!==null)
			{
				if ((raw_entry.memo!==null)&&(raw_entry.memo!==undefined))
				{
					if (newdok_enable_memo_printing)
					{
						handleErrorFunc("memo: "+raw_entry.memo);
					}
				}
			}
		}
	};
	
	var cacheFindMissing = function(first, last)
	{
		var ret = new Array();
			
		var at;
		for(at=first; at<=last; at++)
		{
			if (cacheLookup(at)===null)
			{
				ret[ret.length] = at;
				//handleErrorFunc("missing: "+at);
			}
		}
		return ret;
	};
	
	
	
	
	
	
	
	
	
	var updateOffset = function(newOffset)
	{
		if (newOffset - numLeftward <0)
		{
			newOffset = numLeftward;
		}
		if (self.totalItems!=-1)
		{
			if (newOffset + numRightward > self.totalItems)
			{
				newOffset = self.totalItems - numRightward;
			}
		}
		//lol
		
		if (newOffset-numLeftward<0)
		{
			//handleErrorFunc("too LOW an offset: "+newOffset);
			return false;
		}
		else if ((self.totalItems!=-1)&&(newOffset+numRightward > self.totalItems))
		{
			//else if ((self.totalItems!=-1)&&(newOffset+numRightward >= self.totalItems))
			//handleErrorFunc("too high an offset: "+newOffset);
			return false;
		}
		//handleErrorFunc("new offset: "+newOffset);
		self.offset = newOffset;
		return true;
	};
	
	var helper_doJSONRequest=function(query)
	{
		//disabled - we don't actually pull the json anymore!
		/*
		self.jsonHandler.request(self.jsonKey, self.jsonTarget, query);
		*/
	};
	
	var requestMissing = function(missing)
	{
		var needed="";
		var i, l = missing.length;
		for (i=0; i<l; i++)
		{
			if (i!=0)
			{
				needed=needed+"_";
			}
			needed+=missing[i];
		}
		if (needed!="")
		{
			var query = "verb=get_filmstrip_cell&thumb_indices="+needed+"&query_string="+self.query_string;
			helper_doJSONRequest(query);
		}
	};
	
	
	var partialUpdate=function(first, last)
	{
		var missing = cacheFindMissing(first,last);
		var at;
		var cellIndex;
		for (at=first,cellIndex=0; at<=last; at++, cellIndex++)
		{
			var raw_entry = cacheLookup(at);
			if (raw_entry === null)
			{
				raw_entry = loading_filmcell_entry;
			}
			var bSetOk;
			bSetOk=updateFilmCellFunc(self.base_id, cellIndex, raw_entry, at);
		}
		requestMissing(missing);
	};
	
	this.updateFilmstrip = function()
	{
		var first = self.offset-numLeftward;
		var last =self.offset+numRightward;
		var count = 1+last - first;
		
		var max = self.totalItems;
		if (max == -1)
		{
			max = count;//lolz!
		}
		
		if (first<0)
		{
			last-=first;
			first=0;
		}
		
		partialUpdate(first, last);
	};
	
	this.onFilmstripData = function (jsonKey, newFilmstripCells)
	{
		//1. merge data:
		cacheMerge(newFilmstripCells);
		
		//2. update if any visible cells have changed:
		self.updateFilmstrip();
		
	};
	
	var registerFilmstripHandler =function()
	{
		return self.jsonHandler.register(self.jsonHandler.allocateHandlerID(), self.onFilmstripData);
	};
	
	this.jsonKey = registerFilmstripHandler();
	
	this.getOffset=function()
	{
		return self.offset;
	};
	
	this.setOffset=function(newOffset)
	{
		if (updateOffset(newOffset))
		{
			//self.updateFilmstrip();
			window.setTimeout(function(){self.updateFilmstrip();},1);
			return true;
		}
		else
		{
			return true;
		}
	}
	
	this.scrollFully=function(delta)//lol experimental hack
	{
		var newIndex;
		if (delta == -1)
		{
			newIndex = 1;
		}
		else
		{
			newIndex = self.totalItems;
			if (newIndex == -1)
			{
				newIndex = 500;//hack
			}
		}
		return self.setOffset(newIndex);
	};
	
	this.scroll= function(delta)
	{
		var newIndex = self.getOffset()+delta;
		return self.setOffset(newIndex);
	};
	
	
	var leftArrowTag = getNode(self.base_id+"_leftArrowLink");
	var rightArrowTag = getNode(self.base_id+"_rightArrowLink");
	
	
	leftArrowTag.onclick = function()
	{
		self.scroll(-1);
		return false;
	};
	rightArrowTag.onclick = function()
	{
		self.scroll(1);
		return false;
	};
	
	if (enable_fastforward_and_rewind)
	{
		var rewindArrowTag = getNode(self.base_id+"_arrow_rewind");
		var fastForwardArrowTag = getNode(self.base_id+"_arrow_fastforward");
		rewindArrowTag.onclick = function()
		{
			self.scrollFully(-1);
			return false;
		};
		fastForwardArrowTag.onclick = function()
		{
			self.scrollFully(1);
			return false;
		};
	}
	
	
	var myKeyHandler = function(kc)
	{
		if (kc == 37)
		{
			self.scroll(-1);
			return false;
		}
		else if (kc==39)
		{
			self.scroll(1);
			return false;
		}
		return true;
	};
	
	this.enableKeyScroll = function()
	{
		document.onkeydown=function(event)
		{//lol ie needes;
			
			//todo:?= only do it if nothing has focus!!!
			if ((event===null)||(event===undefined))
			{	//lol@msie!:
				//var event = window.event;
				event = window.event;
			}
			
			if (!isInFormField())
			{
				var kc;
				kc=event.keyCode;
				return myKeyHandler(kc);
			}
		};
	};
	
	this.loadDirect=function(json_newCells, bRefresh)//lol
	{
		cacheMerge(json_newCells);
		if (bRefresh)
		{
			self.updateFilmstrip();
		}
	};
	
	return this;
}

var myFilmstrip = null;
newdok_jsonHandler = new newdok_jsonHandler("default");
newdok_jsonHandler.setDebugFunc(debugMessage);