function ImgRec(guid, url, width, height)
{
	ir = new Object();
	ir.guid = guid;
	ir.url = url;
	ir.width = width;
	ir.height = height;
	return ir;
}

function Asirra_OnLoadTrampoline(phase, index)
{
	// For some reason, FF occasionally decides
	// that my global object, which has been around since
	// the page loads, isn't always there. Grrr.
	asirraState.ImageOnLoadHandler(phase, index);
}

function AsirraState_Super()
{
	this.AsirraRoot = "//challenge.asirra.com";
	this.AsirraExecutable = "/cgi/Asirra?"

	this.numChoices = 12;
	this.userChoseCats = new Array(this.numChoices);
	this.hiddenTicketField = null;
	this.debugField = null;
	this.solved = false;

	this.CreateAsirraHTML = function(htmlString)
	{
		// Find the insertion point, without using document.write, which is deprecated
		var allScriptElements = document.getElementsByTagName("script");
		var insertionPoint = allScriptElements[allScriptElements.length - 1].parentNode;

		// create hidden input field
		this.hiddenTicketField = document.createElement("input");
		this.hiddenTicketField.type="hidden";
		this.hiddenTicketField.name="Asirra_Ticket";
		this.hiddenTicketField.id="Asirra_Ticket";
		insertionPoint.appendChild(this.hiddenTicketField);

		// create main Asirra div
		var tmp = document.createElement("div");
		tmp.id = "AsirraDiv";
		tmp.style.visibility = "hidden";
		tmp.innerHTML = htmlString
		insertionPoint.appendChild(tmp);
	};

	this.InvokeAsirra = function(urlarguments)
	{
		url = this.AsirraRoot + this.AsirraExecutable + urlarguments + "&rand=" + Math.random()
		var newScriptNode = document.createElement("script");
		newScriptNode.type="text/javascript";
		newScriptNode.src= url;
		document.getElementsByTagName("head")[0].appendChild(newScriptNode);

		if (false)
		{
			debugLink = document.createElement("a");
			debugLink.href = url;
			//debugLink.setAttribute("href") = url;
			debugLink.innerHTML = "Link to "+url;
			asirraDiv = document.getElementById("AsirraDiv");
			asirraDiv.appendChild(debugLink);
		}
	};

	this.ResetSelections = function ()
	{
		for (var i=0; i<this.numChoices; i++)
		{
			this.userChoseCats[i] = 0;
		}
	};

	this.UserChoiceString = function()
	{
		var phi;
		var choiceString = "";
		for (phi = 0; phi<this.numChoices; phi++)
		{
			choiceString += this.userChoseCats[phi];
		}
		return choiceString;
	};

	this.NewSession = function()
	{
		this.InvokeAsirra("action=CreateSession");
	};

	this.NewSessionComplete = function(version, sessionID)
	{
		this.serverVersion = version;
		this.sessionID = sessionID;

		// Server now sends a challenge along with new sessions.
		// After this callabck completes, GetChallengeComplete is called.
	};

	this.GetChallenge = function()
	{
		this.InvokeAsirra("action=GetChallenge&sessionId="+this.sessionID);
	};

	this.DrawUserSelections = function ()
	{
		var phi;
		for (phi = 0; phi<this.numChoices; phi++)
		{
			this.DrawSelectedState(phi, this.userChoseCats[phi]);
		}
	}

	this.SetWidgetVisibility = function (visible)
	// visible \in { 'hidden', 'visible' }
	{
		document.getElementById('AsirraDiv').style.visibility = visible;
	}

	this.GetChallengeComplete = function(imageArray)
	{
		this.ResetSelections();
		this.DrawUserSelections();

		this.imageArray = imageArray;

		phase = (new Date()).getTime();
		this.waitingForImagePhase = phase;
		this.waitingForImageCount = this.imageArray.length;

		var phi;
		for (phi = 0; phi<this.numChoices; phi++)
		{
			this.HideImageIndex(phi);
		}

		this.loadQueue = new Array();
		for (phi = 0; phi<this.numChoices; phi++)
		{
			// TODO defer until all images are onload()ed
			var imageRec = this.imageArray[phi];

			href = this.AsirraRoot + this.AsirraExecutable;
			href += "action=AdoptRedirect";
			href += "&sessionId=" + this.sessionID;
			href += "&guid=" + imageRec.guid;
			imageRec.adoptHref = href


			//img = document.createElement("img");
			img = new Image();
			img.onload = function(e) {
				var phi_copy = phi;
				Asirra_OnLoadTrampoline(phase, phi_copy-3);
			};
			img.src = imageRec.url;
			this.loadQueue[phi] = img;
		}

		this.SetWidgetVisibility("visible");
	};

	this.ImageOnLoadHandler = function (phase, index)
	{
		//this.Say("<br>ImageOnLoadHandler("+phase+","+index+")");
		if (phase != this.waitingForImagePhase)
		{
			return;
		}

		//this.ImageAvailable(index, this.GetImageRec(index));
		if (this.waitingForImageCount == 1)
		{
			// last image just showed up
			for (var i=0; i<this.numChoices; i++)
			{
				this.ImageAvailable(i, this.GetImageRec(i));
			}
		}

		if (this.waitingForImageCount > 0)
		{
			this.waitingForImageCount = this.waitingForImageCount - 1;
		}
		else
		{
			this.Say("<br>weird, an extra ImageOnLoadHandler arrived.");
		}
	};
	
	this.ValidateUserSelections = function(responseCompletion)
	{
		//this.Say("<br>Scoring: "+this.UserChoiceString());
		this.responseCompletion = responseCompletion;
		this.InvokeAsirra("action=ScoreResponse"
				 + "&sessionId=" + this.sessionID
				 + "&response="+ this.UserChoiceString()
		);
	};

	this.ScoreResponseComplete = function(serviceSecret)
	{
		//alert("ScoreResponseComplete "+serviceSecret);
		if (serviceSecret != null)
		{
			ticket = serviceSecret;
			this.hiddenTicketField.value = ticket;
			this.solved = true;
			this.responseCompletion(true);
		}
		else
		{
			this.responseCompletion(false);
			// Server now sends a new challenge along with failed responses.
			// After this callabck completes, GetChallengeComplete is called.
		}
	};

	this.Adopt = function(guid)
	{
		this.InvokeAsirra("action=Adopt"
				  + "&sessionId=" + this.sessionID
				  + "&guid=" + guid);
	};

	this.AdoptComplete = function(adoptUrl)
	{
		// Launch new window with adoptUrl link
		open(adoptUrl, "AdoptWindow");
		// Adopt resets the stage; load new pets
		this.GetChallenge();
	};

	this.GetImageRec = function(index)
	{
		return this.imageArray[index];
	}

	this.ToggleIndex = function(index)
	{
		if (this.userChoseCats[index]==1)
		{
			this.userChoseCats[index] = 0;
		}
		else
		{
			this.userChoseCats[index] = 1;
		}
		this.DrawSelectedState(index, this.userChoseCats[index]);
	}
}

function Asirra_CheckIfHuman(completionCallback)
{
	asirraState.ValidateUserSelections(completionCallback);
	return false;
}


function AsirraState_Ver2()
{
	// Declare that this class inherits from superclass
	this.superClass = AsirraState_Super;
	this.superClass();

	this.currentEnlargedImageNumber = null;

	this.cellsPerRow = 6;
	this.numImages = 12;

	this.tableCellInnerWidth = 40;
	this.tableCellOuterWidth = this.tableCellInnerWidth + 18;
	this.tableCellInnerHeight = 40;
	this.tableCellOuterHeight = this.tableCellInnerHeight + 3;

	this.Setup = function ()
	{
		// this generates a variable called myHTML
		var myHTML = '';
myHTML += '<div  id="asirra_MainDiv" style="text-align: left; width: 400px">\n';
myHTML += '	<table cellpadding="0" cellspacing="0" id="asirra_LayoutTable">\n';
myHTML += '		<tr><td colspan=4>\n';
myHTML += '			<div style="padding-bottom:5px" class="InstructionsTextClass" id="asirra_InstructionsTextId">\n';
myHTML += '				W celu weryfikacji zaznacz wszystkie zdjęcia kotów:\n';
myHTML += '			</div>\n';
myHTML += '		</td></tr>\n';
myHTML += '		<tr>\n';
myHTML += '			<td width="270">\n';
myHTML += '				<div\n';
myHTML += '					style="position: relative; border: 1px solid #DDDDDD; width:270px; padding: 5px"\n';
myHTML += '					id="asirra_ChallengeTableDiv">\n';
myHTML += '					<!-- top: -20px ignores variable font size. For some reason it just works anyway in IE, and z-index: 10 keeps it on top in FF. Wish IEs z-index actually worked. -->\n';
myHTML += '						<table cellpadding="0" cellspacing="3" border="0" id="asirra_ChallengeTable" style="position: relative">\n';
myHTML += '							<tbody align="center" valign="center" cellspacing="0" id="asirra_ChallengeTableBody">\n';
myHTML += '							</tbody>\n';
myHTML += '						</table>\n';
myHTML += '				</div>\n';
myHTML += '			</td>\n';
myHTML += '			<td width="10px">\n';
myHTML += '				&nbsp;\n';
myHTML += '			</td>\n';
myHTML += '			<td valign=top>\n';
myHTML += '				<table id="asirra_KnobsTable">\n';
myHTML += '					<tr>\n';
myHTML += '						<td>\n';
myHTML += '							<a href="javascript:asirraState.GetChallenge()"\n';
myHTML += '								title="Pokaż inne zdjęcia.">\n';
myHTML += '								<img width="22" height="22" id="asirra_HipReloadImg" border=0>\n';
myHTML += '							</a>\n';
myHTML += '						</td>\n';
myHTML += '					</tr>\n';
myHTML += '					<tr>\n';
myHTML += '						<td>\n';
myHTML += '							<a href="http://research.microsoft.com/asirra/whatsthis.html"\n';
myHTML += '								title="Co to jest?"\n';
myHTML += '								target="_blank" rel="external"><img border=0 width="22" height="22" id="asirra_HipHelpImg"></a>\n';
myHTML += '						</td>\n';
myHTML += '					</tr>\n';
myHTML += '				</table>\n';
myHTML += '			</td>\n';
myHTML += '			<td valign=top>\n';
myHTML += '				<div id="asirra_EnlargedPositionRightCell">\n';
myHTML += '				</div>\n';
myHTML += '			</td>\n';
myHTML += '		</tr>\n';
myHTML += '	</table>\n';
myHTML += '	<div id="asirra_EnlargedDivContainer"\n';
myHTML += '		style="z-index: 2; height: 12; width: 0; text-align: center; position: relative">\n';
myHTML += '		<div id="asirra_EnlargedDiv"\n';
myHTML += '			style="visibility: hidden; position: absolute; width: 250; height: 250; border: 1px solid #DDDDDD; background-color: #ffffff">\n';
myHTML += '			<div id="asirra_EnlargedDivOverlay"\n';
myHTML += '				style="position: absolute; width: 250; height: 250; background-color: transparent;" >\n';
myHTML += '				<table width="100%" height="100%" border=0\n';
myHTML += '					style="background-color: transparent;"\n';
myHTML += '					><tr><td valign=bottom align=center\n';
myHTML += '					style="background-color: transparent; vertical-align: bottom;">\n';
myHTML += '					<img src="" width=1 height=1>\n';
myHTML += '				</td></tr></table>\n';
myHTML += '			</div>\n';
myHTML += '			<img>\n';
myHTML += '		</div>\n';
myHTML += '	</div>\n';
myHTML += '\n';
myHTML += '	<div style="display:None;" id="Asirra_CellPrototypeDiv">\n';
myHTML += '		<div\n';
myHTML += '				onmouseover="asirraState.Enlarge(event)"\n';
myHTML += '				onmouseout="asirraState.Unenlarge()"\n';
myHTML += '				onclick="asirraState.Image_Selected();"\n';
myHTML += '				style="cursor: pointer;"\n';
myHTML += '		>\n';
myHTML += '			<div style="position: relative; top: 0px; left: 0px; width: 40px; height: 40px"\n';
myHTML += '			>\n';
myHTML += '				<div style="position: absolute; top: 0px; left: 0px;">\n';
myHTML += '					<img id="imgProto">\n';
myHTML += '				</div>\n';
myHTML += '				<div style="position: absolute; top: 0px; left: 0px; display:block">\n';
myHTML += '					<img id="asirra_borderImgProto">\n';
myHTML += '				</div>\n';
myHTML += '			</div>\n';
myHTML += '			<div style="visibility: hidden">\n';
myHTML += '				<a href="adopt"\n';
myHTML += '					onclick="javascript:asirraState.GetChallenge();"\n';
myHTML += '					target="_blank"\n';
myHTML += '					rel="external"></a>\n';
myHTML += '			</div>\n';
myHTML += '		</div>\n';
myHTML += '	</div>\n';
myHTML += '</div>\n';
myHTML += '\n';

		this.CreateAsirraHTML(myHTML);

		document.getElementById("asirra_borderImgProto").src =
			this.AsirraRoot + "/images/border5.gif";
		document.getElementById("asirra_HipHelpImg").src =
			this.AsirraRoot + "/images/hip_help.gif";
		document.getElementById("asirra_HipReloadImg").src =
			this.AsirraRoot + "/images/hip_reload.gif";

		this.SetEnlargedPosition("top");
		this.PopulateTable();
		this.NewSession();
	};

	this.Image_Selected = function ()
	{
		this.ToggleIndex(this.currentEnlargedImageNumber);
	}

	this.DrawSelectedState = function(index, state)
	{
		id = "asirra_borderImg" + index;
		borderImage = document.getElementById(id);
		//this.Say("<br>Found id "+id+" on "+borderImage);
		if (state)
		{
			borderImage.style.display = "block";
		}
		else
		{
			borderImage.style.display = "none";
		}
	}

	this.Unenlarge = function ()
	{
		var ediv = document.getElementById("asirra_EnlargedDiv");
		ediv.style.visibility = "hidden";

		this.GetAdoptDiv(this.currentEnlargedImageNumber).style.visibility = "hidden";

		this.currentEnlargedImageNumber = null;
	}

	this.GetAdoptDiv = function(number)
	{
		return document.getElementById("asirra_AdoptMeDiv"+number);
	}

	this.NumberFromEvent = function(event)
	{
		obj = event.target;	// FF
		if (obj==null)
		{
			obj = event.srcElement;	// IE
		}

		/*
		   this.Say("<p>Keys");
		   for (var key in event)
		   {
		   this.Say("<br>Key "+key+" value="+event[key]);
		   }
		   */
		   
		while (obj != null)
		{
			if (obj.imageNumber != null)
			{
				return obj.imageNumber;
			}
			obj = obj.parentNode;
		}
		return null;
	}

	this.Enlarge = function (event)
	{
		//this.Say("Enlarge ");
		number = this.NumberFromEvent(event);
		if (number==null)
		{
			//this.Say("<br>unable to find number for event.");
			return;
		}

		var ediv = document.getElementById("asirra_EnlargedDiv");
		var imTag = ediv.getElementsByTagName("img")[1];
		var imageRec = this.GetImageRec(number);
		imTag.width = imageRec.width;
		imTag.height = imageRec.height;
		imTag.src = imageRec.url;

		this.currentEnlargedImageNumber = number;
		this.GetAdoptDiv(this.currentEnlargedImageNumber).style.visibility = "visible";

		ediv.style.visibility = "visible";
	}

	this.PopulateTable = function()
	{
		var tableBody = document.getElementById("asirra_ChallengeTableBody");
		var protoDiv = document.getElementById("Asirra_CellPrototypeDiv");

		// Remove existing children
		while (tableBody.firstChild)
		{
			tableBody.removeChild(tableBody.firstChild);
		}

		var trElt;
		var numRows = 0;
		for (var index = 0; index < this.numImages; index++)
		{
			if (index%this.cellsPerRow == 0)
			{
				trElt = document.createElement("tr");
				tableBody.appendChild(trElt);
				numRows += 1;
			}
			 
			var copyDiv = protoDiv.getElementsByTagName("div")[0].cloneNode(true);

			copyDiv.imageNumber = index;

			copyDiv.style.display = "block";

			var imgElt = copyDiv.getElementsByTagName("img")[0];
			imgElt.id = "asirra_img"+index;
			imgElt.width = this.tableCellInnerWidth;
			imgElt.height = this.tableCellInnerHeight;

			var borderImgElt = copyDiv.getElementsByTagName("img")[1];
			borderImgElt.id = "asirra_borderImg"+index;
			//this.Say("<br>Set id "+borderImgElt.id+" on "+borderImgElt);
			borderImgElt.width = this.tableCellInnerWidth;
			borderImgElt.height = this.tableCellInnerHeight;
			borderImgElt.style.display = "none";

			var adoptAElt = copyDiv.getElementsByTagName("a")[0];
			var adoptDivElt = adoptAElt.parentNode;
			adoptDivElt.id = "asirra_AdoptMeDiv"+index;

			var tdElt = document.createElement("td");
			tdElt.appendChild(copyDiv);
			trElt.appendChild(tdElt);
		}
	}

	this.Say = function(s)
	{
		document.getElementById("debugDiv").innerHTML += s;
	}

	this.SetEnlargedPosition = function (position)
	{
		edc = document.getElementById("asirra_EnlargedDivContainer");
		ed = document.getElementById("asirra_EnlargedDiv");
		layoutTable = document.getElementById("asirra_LayoutTable");
		mainDiv = document.getElementById("asirra_MainDiv");
		//leftCell = document.getElementById("asirra_EnlargedPositionLeftCell");
		rightCell = document.getElementById("asirra_EnlargedPositionRightCell");
		curParent = edc.parentNode;

		curParent.removeChild(edc);
		edc.style.top = "0px";
		edc.style.left = "0px";
		edc.style.width = "0px";

		if (position=="top" || position=="bottom")
		{
			var tableWidth = (this.cellsPerRow) * this.tableCellOuterWidth;
			var edWidth = 250;
			//edc.style.left = (tableWidth - edWidth)/2;
			edc.style.left = 0;
			edc.style.width = tableWidth+"px";
			//ed.style.marginLeft = "auto";
			//ed.style.marginRight = "auto";
			ed.style.left = ((tableWidth-250)/2)+"px";

			if (position=="top")
			{
				mainDiv.insertBefore(edc, layoutTable);
				edc.style.top = "-245px";
			}
			else if (position=="bottom")
			{
				mainDiv.insertBefore(edc, layoutTable.nextSibling);
				edc.style.top = "6px";
			}
		}
		else if (position=="left")
		{
			mainDiv.insertBefore(edc, layoutTable);
			edc.style.left = "-253px";
		}
		else if (position=="right")
		{
			rightCell.appendChild(edc);
		}
	}

	this.SetCellsPerRow = function (cellsPerRow)
	{
		this.cellsPerRow = cellsPerRow;
		this.PopulateTable();
	}

	this.ImageAvailable = function(index, imageRec)
	{
		var imgIdStr = "asirra_img"+index;
		var imgElt = document.getElementById(imgIdStr);
		if (imgElt != undefined)
		{
			imgElt.src = this.GetImageRec(index).url;
			imgElt.style.visibility = "visible";
			this.GetAdoptDiv(index).getElementsByTagName("a")[0].href = this.GetImageRec(index).adoptHref;
		}
	}

	this.HideImageIndex = function(index)
	{
		var imgIdStr = "asirra_img"+index;
		var imgElt = document.getElementById(imgIdStr);
		if (imgElt != undefined)
		{
			imgElt.style.visibility = "hidden";
		}
	}

}

var asirraState = new AsirraState_Ver2();
asirraState.Setup();
