var box;
var deltaX, deltaY;

var overlayed = false;

var ROTATE_TIME = 4000;

var VOTE_LEFT = 0;
var VOTE_RIGHT = 1;
var NO_VOTE = 2;
var vote = VOTE_LEFT;

var TOP_SHEET = 0;
var BOTTOM_SHEET = 1;
var NO_SHEET = 2;

var currentBallotNumber = -1;


var explorer = false;
var overBallot = false;

var NORMAL = 0
var FLIPPED = 1;
var UNKNOWN = 2;
var ballotTopFlip = NORMAL;
var ballotBottomFlip = NORMAL

var numAuditedBallots = 0;
var numVotedBallots = 0;

// this is used to prevent half voting and then switching to another ballot,
// leaving the system in an inconsistent state
var votingWindowOpen = false;

// tracks what row is highlighted for showing a vote in step 1
var NO_ROW = -1;
var highlightedRow = NO_ROW;

//////////////////////////////////////////////////
// AJAX functionality
/////////////////////////////////////////////////
function windowLoaded(evt) {

	/* boolean if we're in internet explorer or not */
	explorer = (window.ActiveXObject);

	// prevent IE text selection while dragging!!! Little-known trick!
	document.body.ondrag = function () { return false; };
	document.body.onselectstart = function () { return false; };
	document.body.onkeypress = explorer ?	function () { if (event.keyCode == 13) return false; } : 
											function (event) { if (event.keyCode == 13) return false; }

}


function createClient() {

	try 
	{
		return (window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
	} 
	catch (e) 
	{ 
		alert("Sorry, your browser is not AJAX-enabled!"); 
	}
}


function loadPage(page_name, destDiv)
{
	var client = createClient();

	client.onreadystatechange = 
					function()
					{
						if (client.readyState == 4 && client.status == 200)
						{
							el = document.getElementById(destDiv);
							el.innerHTML = client.responseText;
							
							if (!explorer)
								el.style.visibility = "visible";

							if ("voting.html" == page_name)
							{
								el.style.width = "700px";
								el.style.height = "300px";

								correctBallotDisplay();

								el.style.visibility = "visible";
							}
						}
					}

	client.open("get",page_name,true);
	client.send(null);
}


///////////////////////////////////
/// utility functions
////////////////////////////////////
function incrementCurrentStep()
{
	// hack for ie event propagation
	if (current_step >= STEP_5)
		return;

	current_step++;
	navigationNumber = current_step;


	el = document.getElementById("step" + navigationNumber);
	el.style.borderColor = "black";
	el.style.color = "black";
}


function discardedBallot()
{
	el = document.getElementById("ballotOverVote");

	if (el.style.left == "0px")
		return TOP_SHEET;
	else
		return BOTTOM_SHEET;
}


	
function correctBallotDisplay()
{
	var a_name = document.getElementById("aNameVote");
	var b_name = document.getElementById("bNameVote");
	var right = document.getElementById("rightLabelVote");
	var left = document.getElementById("leftLabelVote");
	var left_hole = document.getElementById("ballotOverLeftHoleVote");
	var right_hole = document.getElementById("ballotOverRightHoleVote");

	div = document.getElementById("ballotNumberTopVote");
	div.innerHTML = "#" + currentBallotNumber;

	div = document.getElementById("ballotNumberBottomVote");
	div.innerHTML = "#" + currentBallotNumber;

	//alert(currentBallotNumber + " " + pTable[currentBallotNumber].topSheet + " " + pTable[currentBallotNumber].bottomSheet);

	if (pTable[currentBallotNumber].topSheet == NORMAL)
	{
		a_name.innerHTML = "A. Al Gore";
		a_name.style.background = "#66E";

		b_name.innerHTML = "B. George W. Bush";
		b_name.style.background = "#6E6";
	}
	else
	{
		a_name.innerHTML = "A. George W. Bush";
		a_name.style.background = "#66E";

		b_name.innerHTML = "B. Al Gore";
		b_name.style.background = "#6E6";
	}


	if (pTable[currentBallotNumber].bottomSheet == NORMAL)
	{
		left.innerHTML = "A";
		left.style.background = "#66E";

		right.innerHTML = "B";
		right.style.background = "#6E6";
	}
	else
	{
		left.innerHTML = "B";
		left.style.background = "#6E6";

		right.innerHTML = "A";
		right.style.background = "#66E";
	}
}




///////////////////////////////////////
// state change functions
///////////////////////////////////////
function continueDemo()
{
	if (current_step >= NUM_NAVIGATION_BOXES)
		return;

	if (votingWindowOpen)
	{
		alert("Finish voting this ballot before going to next step");
		return;
	}


	if (current_step == STEP_3 && numAuditedBallots < NUMBER_BALLOTS)
	{
		alert("You must audit " + NUMBER_BALLOTS + " ballots to continue");
		return;
	}
	else if (current_step == STEP_4 && numVotedBallots < NUMBER_BALLOTS)
	{
		alert("You must vote with " + NUMBER_BALLOTS + " ballots to continue");
		return;
	}

	incrementCurrentStep();

	navigateToStep(current_step);
}


function voteLeft(evt, whichSheet) {
	evt = new Evt(evt);

	if (pTable[currentBallotNumber].voteSide == NO_VOTE && overlayed)
	{
		var ballot_under = document.getElementById("leftLabelVote");
		var ballot_over = document.getElementById("ballotOverLeftHoleVote");

		ballot_under.style.background = "red";
		ballot_under.style.borderColor = "red";
		ballot_over.style.borderColor = "red";

		pTable[currentBallotNumber].voteSide = VOTE_LEFT;

		evt.consume();
	}
}


function voteRight(evt, whichSheet) {
	evt = new Evt(evt);

	if (pTable[currentBallotNumber].voteSide == NO_VOTE && overlayed)
	{
		var ballot_under = document.getElementById("rightLabelVote");
		var ballot_over = document.getElementById("ballotOverRightHoleVote");

		ballot_under.style.background = "red";
		ballot_under.style.borderColor = "red";
		ballot_over.style.borderColor = "red";

		pTable[currentBallotNumber].voteSide = VOTE_RIGHT;

		evt.consume();
	}
}



/////////////////////////////////////////////
// functions for auditing demo
/////////////////////////////////////////////
function clickPTable(num)
{
	if (current_step == STEP_4 && 
		!pTable[num].audited && 
		pTable[num].voteSide == NO_VOTE && 
		numVotedBallots < NUMBER_BALLOTS &&
		!votingWindowOpen)
	{
		currentBallotNumber = num;

		loadPage("voting.html", "popup");

		votingWindowOpen = true;
		shredded = false;
		numVotedBallots++;
	}
	else if (current_step == STEP_1 &&
			!pTable[num].audited && 
			pTable[num].voteSide == NO_VOTE &&
			!votingWindowOpen)
	{
		currentBallotNumber = num;

		loadPage("voting.html", "popup");

		// clear the old voting row
		if (highlightedRow != NO_ROW)
		{
			hideLinkedRows(highlightedRow);
			highlightedRow = NO_ROW;
		}

		votingWindowOpen = true;
		shredded = false;
	}
}

function clickRTable(num)
{
	if (current_step == STEP_5 && rTable[num].candidateVote != NO_VOTE)
	{
	}
}


// show audit information
function compareDoorsPreAudit(num)
{
	el = document.getElementById("popup");

	//el.style.top = topPx + "px";
	//el.style.left = leftPx + "px";
	el.style.width = "150px";
	
	voteFlips = pTable[dTable[num].voteRow].topSheet + pTable[dTable[num].voteRow].bottomSheet;
	decryptionFlips = dTable[num].topSheet + dTable[num].bottomSheet;

	text = "Decryption Table #" + num + "<br/><br/>";
	text += "Print Table<br/>&nbsp;&nbsp;Flips:" + voteFlips + "<br/>&nbsp;&nbsp;Door #" + ((voteFlips%2)+1) + "<br/><br/>";
	text += "Decryption Table<br/>&nbsp;&nbsp;Flips:" + decryptionFlips + "<br/>&nbsp;&nbsp;Door #" + ((decryptionFlips%2)+1) + "<br/>"  + closePopupText;

	el.innerHTML = text;
	el.style.visibility = "visible";
}


// show audit information
function compareDoorsPostAudit(num)
{
	node = document.getElementById("table1");

	topPx = parseInt(node.style.top) - 200;
	leftPx = parseInt(node.style.left);

	el = document.getElementById("popup");

	//el.style.top = topPx + "px";
	//el.style.left = leftPx + "px";
	el.style.width = "150px";
	
	if (dTable[num].postElectionAudit == LEFT_AUDIT)
	{
		flips = pTable[dTable[num].voteRow].voteSide + dTable[num].topSheet;
		result = dTable[num].intermediateVote;

		text = "Decryption Table #" + num + "<br/><br/>";
		text += "Left Audit<br/>&nbsp;&nbsp;Flips:" + flips + "<br/>&nbsp;&nbsp;Door #" + ((flips%2)+1) + "<br/><br/>";

		if (result == NORMAL)
			text += "Intermediate Value<br/>&nbsp;&nbsp;Normal<br/>&nbsp;&nbsp;Door #" + ((result%2)+1) + "<br/>"  + closePopupText;
		else //if (result == NORMAL)
			text += "Intermediate Value<br/>&nbsp;&nbsp;Flipped<br/>&nbsp;&nbsp;Door #" + ((result%2)+1) + "<br/>"  + closePopupText;

	}
	else
	{
		flips = dTable[num].intermediateVote + dTable[num].bottomSheet;
		result = rTable[dTable[num].resultRow].candidateVote

		text = "Decryption Table #" + num + "<br/><br/>";
		text += "Right Audit<br/>&nbsp;&nbsp;Flips:" + flips + "<br/>&nbsp;&nbsp;Door #" + ((flips%2)+1) + "<br/><br/>";
		text += "Result Value<br/>&nbsp;&nbsp;Candidate:" + rTable[dTable[num].resultRow].toString() + "<br/>&nbsp;&nbsp;Door #" + ((result%2)+1) + "<br/>"  + closePopupText;
	}


	el.innerHTML = text;
	el.style.visibility = "visible";
}




function clickDTable(num)
{
	if (current_step == STEP_3)
	{
		if (numAuditedBallots < NUMBER_BALLOTS && !dTable[num].audited)
		{
			numAuditedBallots++;

			rRow = dTable[num].resultRow;
			vRow = dTable[num].voteRow;

			//alert("result:" + rRow + " vote:" + vRow);

			rTable[rRow].audited = true;
			el = document.getElementById("rRowFader" + rRow);
			setOpacity(el, 0.0);
			
			pTable[vRow].audited = true;
			el = document.getElementById("pRowFader" + vRow);
			setOpacity(el, 0.0);

			dTable[num].audited = true;
			el = document.getElementById("dRowFader" + num);
			setOpacity(el, 0.0);

			compareDoorsPreAudit(num);

			showLinkedRows(num);
		}
		else if (dTable[num].audited)
		{
			compareDoorsPreAudit(num);
		}
	}
	else if (current_step == STEP_5 && !dTable[num].audited)
	{
		if (dTable[num].postElectionAudit == NO_AUDIT)
		{
			node = document.getElementById("table2");

			topPx = parseInt(node.style.top) + 60 + num*17;
			leftPx = parseInt(node.style.left);

			el = document.getElementById("auditPopup");

			el.style.top = topPx + "px";
			el.style.left = leftPx + "px";
			el.style.width = "215px";

			text = auditPopupText[0] + num + auditPopupText[1] + num + auditPopupText[2];

			el.innerHTML = text;
			el.style.visibility = "visible";
		}
		else
		{
			compareDoorsPostAudit(num);
		}
	}
}


function auditLeft(i)
{
	if (dTable[i].postElectionAudit == NO_AUDIT)
	{
		el = document.getElementById("dRowFader" + i);
		el.style.left = "176px";
		el.style.width = "85px";

		dTable[i].postElectionAudit = LEFT_AUDIT;

		el = document.getElementById("auditPopup");
		el.style.visibility = "hidden";

		compareDoorsPostAudit(i);
	}
}

function auditRight(i)
{
	if (dTable[i].postElectionAudit == NO_AUDIT)
	{
		el = document.getElementById("dRowFader" + i);
		el.style.width = "85px";

		dTable[i].postElectionAudit = RIGHT_AUDIT;

		el = document.getElementById("auditPopup");
		el.style.visibility = "hidden";

		compareDoorsPostAudit(i);
	}
}



////////////////////////////////////////
// mouse over functions for the rows
///////////////////////////////////////
// return the value of D that highlights the P row
function showLinkedRowsFromP(num)
{
	for (i = 0; i < dTable.length; i++)
	{
		if (num == dTable[i].voteRow)
		{
			showLinkedRows(i);
			return i;
		}
	}
}

function hideLinkedRowsFromP(num)
{
	for (i = 0; i < dTable.length; i++)
	{
		if (num == dTable[i].voteRow)
		{
			hideLinkedRows(i);
			break;
		}
	}
}

function showLinkedRowsFromR(num)
{
	for (i = 0; i < dTable.length; i++)
	{
		if (num == dTable[i].resultRow)
		{
			showLinkedRows(i);
			break;
		}
	}
}

function hideLinkedRowsFromR(num)
{
	for (i = 0; i < dTable.length; i++)
	{
		if (num == dTable[i].resultRow)
		{
			hideLinkedRows(i);
			break;
		}
	}
}


function showLinkedRows(num)
{
	// highlight the r and p rows
	str = "pRow" + dTable[num].voteRow;
	str2 = "rRow" + dTable[num].resultRow;

	el = document.getElementById(str);
	el.style.border = "1px solid red";
	el = document.getElementById(str2);
	el.style.border = "1px solid red";

	// highlight the d rows
	str1 = "dRow" + num;
	el = document.getElementById(str1);
	el.style.border = "1px solid red";
}


function hideLinkedRows(num)
{
	// highlight the r and p rows
	str = "pRow" + dTable[num].voteRow;
	str2 = "rRow" + dTable[num].resultRow;

	el = document.getElementById(str);
	el.style.border = "1px solid #DDD";
	el = document.getElementById(str2);
	el.style.border = "1px solid #DDD";

	// highlight the d rows
	str1 = "dRow" + num;
	el = document.getElementById(str1);
	el.style.border = "1px solid #DDD";
}


function mouseOverDRow(num)
{
	// make the cursor show as default if we can't click
	if (votingWindowOpen)
	{
		str = "dRow" + num;

		el = document.getElementById(str);
		el.style.cursor = "default";

		return;
	}

	if (highlightedRow != NO_ROW)
		showLinkedRows(highlightedRow);


	switch (current_step)
	{
	case STEP_1:
		
		showLinkedRows(num);

		break;

	case STEP_3:

		if (!dTable[num].audited && numAuditedBallots < NUMBER_BALLOTS)
		{
			// highlight the d rows
			str1 = "dRow" + num;
			el = document.getElementById(str1);
			el.style.border = "1px solid red";
			el.style.cursor = "pointer";
		}
		else if (dTable[num].audited)
		{
			str1 = "dRow" + num;
			el = document.getElementById(str1);
			el.style.cursor = "pointer";

			showLinkedRows(num);
		}
		else
		{
			el = document.getElementById("dRow" + num);
			el.style.cursor = "default";
		}

		break;

	case STEP_4:
		if (dTable[num].audited)
			showLinkedRows(num);


		break;

	case STEP_5:
		if (dTable[num].audited)
		{
			showLinkedRows(num);

			el = document.getElementById("dRow" + num);
			el.style.cursor = "default";
		}
		else
		{
			el = document.getElementById("dRow" + num);
			el.style.cursor = "pointer";
			el.style.border = "1px solid red";


			if (dTable[num].postElectionAudit == LEFT_AUDIT)
			{
				str = "pRow" + dTable[num].voteRow;

				el = document.getElementById(str);
				el.style.border = "1px solid red";
			}
			else if (dTable[num].postElectionAudit == RIGHT_AUDIT)
			{
				str2 = "rRow" + dTable[num].resultRow;

				el = document.getElementById(str2);
				el.style.border = "1px solid red";
			}
		}

		break;
	}
}

function mouseOutDRow(num)
{
	str1 = "dRow" + num;
	el = document.getElementById(str1);
	el.style.border = "1px solid #DDD";

	if (current_step == STEP_1 || dTable[num].audited)
	{
		str = "pRow" + dTable[num].voteRow;
		str2 = "rRow" + dTable[num].resultRow;

		el = document.getElementById(str);
		el.style.border = "1px solid #DDD";
		el = document.getElementById(str2);
		el.style.border = "1px solid #DDD";
	}


	if (current_step == STEP_5 && dTable[num].postElectionAudit == LEFT_AUDIT)
	{
		str = "pRow" + dTable[num].voteRow;

		el = document.getElementById(str);
		el.style.border = "1px solid #DDD";
	}
	else if (current_step == STEP_5 && dTable[num].postElectionAudit == RIGHT_AUDIT)
	{
		str2 = "rRow" + dTable[num].resultRow;

		el = document.getElementById(str2);
		el.style.border = "1px solid #DDD";
	}

}


function mouseOverPRow(num)
{
	// make the cursor show as default if we can't click
	if (votingWindowOpen)
	{
		str = "pRow" + num;

		el = document.getElementById(str);
		el.style.cursor = "default";

		return;
	}

	if (highlightedRow != NO_ROW)
		showLinkedRows(highlightedRow);

	if (current_step == STEP_4 && !pTable[num].audited && pTable[num].voteSide == NO_VOTE)
	{
		str = "pRow" + num;

		el = document.getElementById(str);
		el.style.border = "1px solid red";
		el.style.cursor = "pointer";
	}
	else if (current_step == STEP_1)
	{
		if (!pTable[num].audited && pTable[num].voteSide == NO_VOTE)
		{
			str = "pRow" + num;
			el = document.getElementById(str);
			el.style.cursor = "pointer";
		}

		showLinkedRowsFromP(num)
	}
	else if (pTable[num].audited)
	{
		showLinkedRowsFromP(num)
	}
}

function mouseOutPRow(num)
{
	if (current_step == STEP_4)
	{
		str = "pRow" + num;

		el = document.getElementById(str);
		el.style.border = "1px solid #DDD";
		el.style.cursor = "default";
	}

	hideLinkedRowsFromP(num);

	if (highlightedRow != NO_ROW)
		showLinkedRows(highlightedRow);
}



function mouseOverRRow(num)
{
	// make the cursor show as default if we can't click
	if (votingWindowOpen)
	{
		str = "rRow" + num;

		el = document.getElementById(str);
		el.style.cursor = "default";

		return;
	}

	if (highlightedRow != NO_ROW)
		showLinkedRows(highlightedRow);

	if (current_step == STEP_1)
	{
		showLinkedRowsFromR(num)
	}
	else if (rTable[num].audited)
	{
		showLinkedRowsFromR(num)
	}
}

function mouseOutRRow(num)
{
	hideLinkedRowsFromR(num);

	if (highlightedRow != NO_ROW)
		showLinkedRows(highlightedRow);
}


function MouseOverVote(evt, name)
{
	evt = new Evt(evt);

	clearTimeout(timeoutID);

	if (overlayed && pTable[currentBallotNumber].voteSide == NO_VOTE)
	{
		el = document.getElementById(name);
		el.style.cursor = "crosshair";
	}
	else
	{
		el = document.getElementById(name);
		el.style.cursor = "pointer";
	}

	mouseOverBallot(evt);

	evt.consume();
}


function mouseOverHeader(evt, id)
{
	evt = new Evt(evt);

	// make the cursor show as default if we can't click
	if (votingWindowOpen)
	{
		el = document.getElementById(id);
		el.style.cursor = "default";
	}
	else
	{
		el = document.getElementById(id);
		el.style.cursor = "pointer";
	}

	evt.consume();
}


function mouseOverBallot(evt)
{
	evt = new Evt(evt);

	overBallot = true;

	evt.consume();
}

function mouseOutBallot(evt)
{
	evt = new Evt(evt);

	overBallot = false;

	evt.consume();
}
