var box;
var deltaX, deltaY;

var BALLOT_OVER_START_Y = 40;
var BALLOT_OVER_START_X = 100;
var BALLOT_UNDER_START_Y = 200;
var BALLOT_UNDER_START_X = 100;
var overlayed = false;

var ROTATE_TIME = 2000;
var NUM_NAVIGATION_BOXES = 6;

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

var TOP_SHEET = 0;
var BOTTOM_SHEET = 1;

var SCANNER = 0;
var SHREDDER = 1;
var COMPUTER = 2;
var BALLOT = 3;


var STEP_0 = 0;
var STEP_1 = 1;
var STEP_2a = 2;
var STEP_2b = 3;
var STEP_2c = 4;
var STEP_3 = 5;
var STEP_4 = 6;
var STEP_5 = 7;
var STEP_6 = 8;
var STEP_7 = 9;
var STEP_8 = 10;
var current_step = STEP_0;

var ballotNumber;
var votedBallotNumber;

var explorer = false;

var popup_text = new Array(
				"<h4>&nbsp&nbsp&nbsp Ballot</h4>Here is your ballot.  In a real election you would go to the polling place and receive a ballot there.",
				"<h4>&nbsp&nbsp&nbsp Ballot <span id='popupBallotNumber'></span></h4> With this configuration, a vote for Dubya would be marked on the left.",
				"<h4>&nbsp&nbsp&nbsp Ballot #1236</h4> With this configuration, a vote for Dubya would be marked on the right.",
				"<h4>&nbsp&nbsp&nbsp Ballot #1237</h4> With this configuration, a vote for Dubya would be marked on the left.",
				"<h4>&nbsp&nbsp&nbsp Top and Bottom Ballots </h4> In a real election, the ballot would be paper.  It would be perforated in the middle so that a voter could simply fold the top over the bottom to line up the holes.  When the ballot is folded for voting, the bottom half only appears through the two holes.",
				"<h4>&nbsp&nbsp&nbsp Bottom Ballot </h4>  to specify how 'A' and 'B' match up with left and right.",
				"<h4>&nbsp&nbsp&nbsp Folded-Over Ballot </h4> If the cursor is placed over 'A' or 'B', the ballot can be marked by clicking the mouse button.  In a real election, an ink dauber, like the ones used in bingo, would be used to make sure both top and bottom ballots are marked.",
				"Both ballots would be necessary for anyone to see how you voted -- remember from before, sometimes a vote for Dubya is left and sometimes it is right.<br />"
				);

var popup_leftVote = "<h4> Left Side </h4>We don't reveal who you voted for, just whether you voted on the right or left side of the ballot! Even if other people go online and enter your ballot number, they won't find out whether you voted for Gore or Bush. <br /><br />But this doesn't mean that your candidate might not get your vote. There is secret information at an election authority that will make absolutely sure that your vote is tallied correctly. If you are interested in finding out how this works, you should check out the <a href='http://punchscan.org/demos/audit/'> audit demo</a>.";
var popup_rightVote = "<h4> Right Side </h4>We don't reveal who you voted for, just whether you voted on the right or left side of the ballot! Even if other people go online and enter your ballot number, they won't find out whether you voted for Gore or Bush. <br /><br />But this doesn't mean that your candidate might not get your vote. There is secret information at an election authority that will make absolutely sure that your vote is tallied correctly. If you are interested in finding out how this works, you should check out the <a href='http://punchscan.org/demos/audit/'> audit demo</a>.";



//////////////////////////////////////////////////
// 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 ("step1_main.html" == page_name)
								correctBallotDisplay(false, true);
							else if ("step2_main.html" == page_name)
								correctBallotDisplay(false, true);
							else if ("step5_main.html" == page_name)
								rotateBallot(true, false, false);
							else if ("computer.html" == page_name)
							{
								el = document.getElementById("checkBallot");
							}
							else if ("step5_text.html" == page_name)
							{
								if (!explorer)
								{
									topOrBottom = document.getElementById("topOrBottom");
									aAndB = document.getElementById("aAndB");

									if (discardedBallot() == TOP_SHEET)
									{
										topOrBottom.innerHTML = "top";
										aAndB.innerHTML = "Gore and Bush";
									}
									else
									{
										topOrBottom.innerHTML = "bottom";
										aAndB.innerHTML = "A and B";
									}

									if (vote == VOTE_RIGHT)
									{
										rightOrLeft = document.getElementById("rightOrLeft");
										rightOrLeft.innerHTML = "right";
									}


								}
							}
						}
					}

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

function setOpacity(node,val) {
	if (node.filters) {
		try {
			node.filters["alpha"].opacity = val*100;
		} catch (e) { }
	} else if (node.style.opacity) {
		node.style.opacity = val;
	}
}

function getX(node) {
	return parseInt(node.style.left);
}

function getY(node) {
	return parseInt(node.style.top);
}

function getWidth(node) {
	return parseInt(node.style.width);
}

function getHeight(node) {
	return parseInt(node.style.height);
}

function setX(node,x) {
	node.style.left = x + "px";
}

function setY(node,y) {
	node.style.top = y + "px";
}

function Evt(evt) {
	this.evt = evt ? evt : window.event; 
	this.source = evt.target ? evt.target : evt.srcElement;
	this.x = evt.pageX ? evt.pageX : evt.clientX;
	this.y = evt.pageY ? evt.pageY : evt.clientY;
}

Evt.prototype.toString = function () {
	return "Evt [ x = " + this.x + ", y = " + this.y + " ]";
};

Evt.prototype.consume = function () {
	if (this.evt.stopPropagation) {
		this.evt.stopPropagation();
		this.evt.preventDefault();
	} else if (this.evt.cancelBubble) {
		this.evt.cancelBubble = true;
		this.evt.returnValue  = false;
	}
};

Evt.addEventListener = function (target,type,func,bubbles) {
	if (document.addEventListener) {
		target.addEventListener(type,func,bubbles);
	} else if (document.attachEvent) {
		target.attachEvent("on"+type,func,bubbles);
	} else {
		target["on"+type] = func;
	}
};

Evt.removeEventListener = function (target,type,func,bubbles) {
	if (document.removeEventListener) {
		target.removeEventListener(type,func,bubbles);
	} else if (document.detachEvent) {
		target.detachEvent("on"+type,func,bubbles);
	} else {
		target["on"+type] = null;
	}
};

function dragPress(evt, id_name) {
	evt = new Evt(evt);

	box = document.getElementById(id_name);

	//box = evt.source;

	//setOpacity(box,.7);

	deltaX = evt.x - getX(box);
	deltaY = evt.y - getY(box);
	Evt.addEventListener(document,"mousemove",dragMove,false);
	Evt.addEventListener(document,"mouseup",dragRelease,false);

	evt.consume();
}

function dragMove(evt) {
	evt = new Evt(evt);
	setX(box,evt.x - deltaX);
	setY(box,evt.y - deltaY);

	if (droppedOnImage(evt) && current_step >= STEP_3)
	{
		box.style.border = "blue 3px solid";
	}
	else
	{
		box.style.border = "black 1px solid";
	}

	evt.consume();
}

function dragRelease(evt) {
	evt = new Evt(evt);
	//setOpacity(box,1);
	Evt.removeEventListener(document,"mousemove",dragMove,false);
	Evt.removeEventListener(document,"mouseup",dragRelease,false);

	if (droppedOnBallot(evt) && current_step == STEP_2a) {
		under = document.getElementById("ballotUnderVote");
		over = document.getElementById("ballotOverVote");
		over.style.top = under.style.top;
		over.style.left = under.style.left;

		overlayed = true;

		if (vote == NO_VOTE)
		{
			loadPage("step2b_text.html", "currentStep");
			incrementCurrentStep();

			closePopup();
		}
	}
	else // return them to their original positions
	{
		if (droppedOnImage(evt) && current_step == STEP_3)
		{
			setupImageDivFor(SCANNER);

			box.style.left = "0px";
			box.style.visibility = "hidden";


			loadPage("step4_text.html", "currentStep");
			loadPage("scanner.html", "imageDiv");

			incrementCurrentStep();
		}
		else if (droppedOnImage(evt) && current_step == STEP_4)
		{
			do
			{
				ballotNumber = get_random();
			}
			while ((ballotNumber % 4) != (votedBallotNumber % 4));

			setupImageDivFor(BALLOT);

			loadPage("step5_text.html", "currentStep");
			loadPage("step5_main.html", "imageDiv");
			
			incrementCurrentStep();
		}
		else if (current_step == STEP_2a || current_step == STEP_2b || current_step == STEP_2c)
		{
			// hack for ie (because event propagation is weird)
			if (!movedOffBallot(evt))
			{
				return;
			}

			under = document.getElementById("ballotUnderVote");
			over = document.getElementById("ballotOverVote");

			over.style.top = BALLOT_OVER_START_Y + "px";
			over.style.left = BALLOT_OVER_START_X + "px";
			under.style.top = BALLOT_UNDER_START_Y + "px";
			under.style.left = BALLOT_UNDER_START_X + "px";

			overlayed = false;

			if (vote == NO_VOTE)
			{
				loadPage("step2a_text.html", "currentStep");
				current_step = STEP_2a;
			}
			else //if (vote == NO_VOTE)
			{
				setupImageDivFor(SHREDDER);

				loadPage("step3_text.html", "currentStep");
				loadPage("shredder.html", "imageDiv");


				incrementCurrentStep();
			}
		}
	}
		

	evt.consume();
}


function droppedOnBallot(evt) {
	var ballot_under = document.getElementById("ballotUnderVote");
	var ballot_over = document.getElementById("ballotOverVote");
	var x = getX(ballot_under);
	var y = getY(ballot_under);
	var x1 = getX(ballot_over);
	var y1 = getY(ballot_over);

	var diff_x = (x > x1 ? x - x1 : x1 - x);
	var diff_y = (y > y1 ? y - y1 : y1 - y);
	
	return diff_x < 50 &&
		   diff_y < 50;
}


function movedOffBallot(evt) {
	var ballot_under = document.getElementById("ballotUnderVote");
	var ballot_over = document.getElementById("ballotOverVote");
	var x = getX(ballot_under);
	var y = getY(ballot_under);
	var x1 = getX(ballot_over);
	var y1 = getY(ballot_over);
	
	return x != x1 || y != y1;
}



function droppedOnImage(evt) {
	var image = document.getElementById("imageDiv");
	var x = getX(image);
	var y = getY(image);
	var x1 = getX(box);
	var y1 = getY(box);

	var diff_x = (x > x1 ? x - x1 : x1 - x);
	var diff_y = (y > y1 ? y - y1 : y1 - y);

	return diff_x < 100 &&
		   diff_y < 100;
}


///////////////////////////////////
/// utility functions
////////////////////////////////////
function get_random()
{
    var ranNum = Math.floor(Math.random()*100);
    return ranNum;
}


function setupImageDivFor(type)
{
	image = document.getElementById("imageDiv");

	if (!explorer)
		image.style.visibility = "hidden";
	else
		image.innerHTML = "";

	switch (type)
	{
	case SHREDDER:
		image.style.top = "65px";
		image.style.left = "380px";
		break;
		
	case COMPUTER:
		image.style.top = "45px";
		image.style.left = "30px";
		break;
		
	case SCANNER:
		image.style.top = "50px";
		image.style.left = "380px";
		break;

	case BALLOT:
		image.style.top = "75px";
		image.style.left = "40px";
		break;

	default:
		alert("weirdess in setup image");
	}
}


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

	current_step++;
	navigationNumber = current_step;

	if (current_step >= STEP_2a && current_step <= STEP_2c)
		navigationNumber = STEP_2a;
	else if (current_step > STEP_2c)
		navigationNumber = current_step - 2;


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

function invalidateNavBoxes(navigationNumber)
{
	for (i = navigationNumber + 1; i <= NUM_NAVIGATION_BOXES; i++)
	{
		el = document.getElementById("step" + i);
		el.style.borderColor = "#999";
		el.style.color = "gray";
	}
}

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

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

/* functions to handle cycling ballot through different configurations */
function rotateBallot(schedule_again, draw_bush_outline, voting_ballot)
{
	if (schedule_again)
		timeoutID_ballot = setTimeout('rotateBallot(' + schedule_again + ',' + draw_bush_outline + ',' + voting_ballot + ')', ROTATE_TIME);


	correctBallotDisplay(draw_bush_outline, voting_ballot);


	if (discardedBallot() == BOTTOM_SHEET)
	{
		// bottom remains
		// we want to swap the top pieces
		if (ballotNumber % 2)
			++ballotNumber;
		else
			ballotNumber += 3;
	}
	else
	{
		// top remains
		// we want to swap the bottom pieces
		if (ballotNumber % 2)
			ballotNumber += 3;
		else
			++ballotNumber;
	}
}


function correctBallotDisplay(draw_bush_outline, voting_ballot)
{
	if (voting_ballot)
	{
		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 = "#" + votedBallotNumber;

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

		localBallotNumber = votedBallotNumber;
	}
	else //if (!voting_ballot)
	{
		var a_name = document.getElementById("aNameExample");
		var b_name = document.getElementById("bNameExample");
		var right = document.getElementById("rightLabelExample");
		var left = document.getElementById("leftLabelExample");
		var left_hole = document.getElementById("ballotOverLeftHoleExample");
		var right_hole = document.getElementById("ballotOverRightHoleExample");

		div = document.getElementById("ballotNumberTopExample");
		div.innerHTML = "#" + ballotNumber;

		div = document.getElementById("ballotNumberBottomExample");
		div.innerHTML = "#" + ballotNumber;

		localBallotNumber = ballotNumber;
	}

	
	if ((localBallotNumber % 4) == 0)
	{
		a_name.innerHTML = "A. Al Gore";
		a_name.style.background = "#66E";

		b_name.innerHTML = "B. George W. Bush";
		b_name.style.background = "#6E6";

		left.innerHTML = "A";
		left.style.background = "#66E";

		right.innerHTML = "B";
		right.style.background = "#6E6";

		if (draw_bush_outline)
		{
			left_hole.style.borderColor = "#888"
			right_hole.style.borderColor = "#E66";
		}
	}
	else if ((localBallotNumber % 4) == 1)
	{
		a_name.innerHTML = "A. George W. Bush";
		a_name.style.background = "#66E";

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

		left.innerHTML = "A";
		left.style.background = "#66E";

		right.innerHTML = "B";
		right.style.background = "#6E6";

		if (draw_bush_outline)
		{
			left_hole.style.borderColor = "#E66";
			right_hole.style.borderColor = "#888"
		}
	}
	else if ((localBallotNumber % 4) == 2)
	{
		a_name.innerHTML = "A. George W. Bush";
		a_name.style.background = "#66E";

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

		left.innerHTML = "B";
		left.style.background = "#6E6";

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

		if (draw_bush_outline)
		{
			left_hole.style.borderColor = "#888"
			right_hole.style.borderColor = "#E66";
		}
	}
	else //if ((localBallotNumber % 4) == 3)
	{
		a_name.innerHTML = "A. Al Gore";
		a_name.style.background = "#66E";

		b_name.innerHTML = "B. George W. Bush";
		b_name.style.background = "#6E6";

		left.innerHTML = "B";
		left.style.background = "#6E6";

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

		if (draw_bush_outline)
		{
			left_hole.style.borderColor = "#E66";
			right_hole.style.borderColor = "#888"
		}
	}

	if (vote != NO_VOTE && voting_ballot)
	{
		if (vote == VOTE_LEFT)
		{
			var ballot_under = document.getElementById("leftLabelVote");
			var ballot_over = document.getElementById("ballotOverLeftHoleVote");
		}
		else
		{
			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";
	}
}


function queryVote(evt)
{
	code = evt.keyCode;

	evt = new Evt(evt);

	if (code == 13)
	{
		evt.consume();
	}

	
	balNum = document.getElementById("checkBallot").value;

	if (votedBallotNumber == balNum)
	{
		el = document.getElementById("popup");

		if (vote == VOTE_LEFT)
		{
			el.innerHTML = popup_leftVote;
		}
		else
		{
			el.innerHTML = popup_rightVote;
		}

		el.style.top = "-120px";
		el.style.left = "60px";
		el.style.visibility = "visible";

		timeoutID = setTimeout("closePopup()", 30000);
	}
	else
	{
		alert("Incorrect Ballot Number");
	}


	evt.consume();

	//return false;
}



///////////////////////////////////////
// navigation functions
///////////////////////////////////////
function startDemo()
{
	incrementCurrentStep();

	votedBallotNumber = ballotNumber = get_random();

	loadPage("step1_main.html", "mainBody");
	loadPage("step1_text.html", "currentStep");
}


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

	if (overlayed && vote == NO_VOTE)
	{
		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";

		vote = VOTE_LEFT;

		loadPage("step2c_text.html", "currentStep");

		incrementCurrentStep();
		closePopup();
	
		evt.consume();
	}
}

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

	if (overlayed && vote == NO_VOTE)
	{
		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";

		vote = VOTE_RIGHT;

		loadPage("step2c_text.html", "currentStep");

		incrementCurrentStep();
		closePopup();

		evt.consume();
	}
}


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

	// first we need to bring up the ballot that the user chose
	loadPage("step2_main.html", "mainBody");
	loadPage("step2a_text.html", "currentStep");

	incrementCurrentStep();

	clearTimeout(timeoutID_ballot);

	evt.consume();
}


function checkVote()
{
	setupImageDivFor(COMPUTER);

	loadPage("computer.html", "imageDiv");
	loadPage("step6_text.html", "currentStep");

	incrementCurrentStep();

	clearTimeout(timeoutID_ballot);
	clearTimeout(timeoutID);
}


/**********************************************
 * Popup Functions
 *********************************************/
var timeoutID;
var lastNodeID = -1;

var timeoutID_ballot;


function MouseOutPopup(e)
{
	timeoutID = setTimeout("closePopup()", 400);
}


function MouseOverPopup(e)
{
	clearTimeout(timeoutID);
}


function MouseOverNode(e, node_id, id_name)
{
	clearTimeout(timeoutID);

	e = new Evt(e);

	src = document.getElementById(id_name);

	if (node_id != lastNodeID)
	{
		if ((node_id == 4 || node_id == 5))
		{
			//if (current_step == STEP_2b)
			//	node_id = 6;
			if (current_step == STEP_2a)
				;
			else
			{
				closePopup();
				return;
			}
		}

		el = document.getElementById("popup");

		g = parseInt(src.style.top) - 20;
		el.style.top = g + "px";

		r = parseInt(src.style.left) + 270;
		el.style.left = r + "px";

		el.innerHTML = popup_text[node_id];

		el.style.visibility = "visible";

		lastNodeID = node_id;
	}

	e.consume();
}

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

	clearTimeout(timeoutID);

	if (overlayed && vote == NO_VOTE)
	{
		el = document.getElementById(name);
		el.style.cursor = "crosshair";
	}
	else
	{
		el = document.getElementById(name);
		el.style.cursor = "pointer";
	}

	evt.consume();
}


function MouseOutNode(e)
{
	timeoutID = setTimeout("closePopup()", 400);
}

function closePopup()
{
	el = document.getElementById("popup");

	el.style.visibility = "hidden";

	lastNodeID = -1;
}


/*************************************
 * Navigation functions
 ******************************/
function mouseOverNavigation(nav_number, evt)
{
	evt = new Evt(evt);

	// must increment for the steps 2a,etc
	if (nav_number > 2)
		nav_number += 2;

	if (nav_number <= current_step)
	{
		evt.source.style.backgroundColor = "#449";
	}


	evt.consume();
}

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

	evt.source.style.backgroundColor = "#DDE";

	evt.consume();
}

function navigateTo(step, evt)
{
	evt = new Evt(evt);

	nav_number = step;

	if (nav_number > STEP_2a)
		nav_number += 2;

	if (nav_number > current_step)
	{
		//alert("can't do it");
		return;
	}

	switch (nav_number)
	{
	case STEP_1:
		current_step = nav_number;
		clearTimeout(timeoutID_ballot);


		votedBallotNumber = ballotNumber = get_random();
		vote = NO_VOTE;
		overlayed = false;

		loadPage("step1_main.html", "mainBody");
		loadPage("step1_text.html", "currentStep");

		invalidateNavBoxes(step);
		break;

	case STEP_2a:
	case STEP_2b:
	case STEP_2c:
		current_step = nav_number;
		clearTimeout(timeoutID_ballot);

		vote = NO_VOTE;
		overlayed = false;

		loadPage("step2_main.html", "mainBody");
		loadPage("step2a_text.html", "currentStep");

		invalidateNavBoxes(step);
		break;

	case STEP_3:
		current_step = nav_number;
		clearTimeout(timeoutID_ballot);

		overlayed = false;

		setupImageDivFor(SHREDDER);
		loadPage("step2_main.html", "mainBody");
		loadPage("step3_text.html", "currentStep");
		loadPage("shredder.html", "imageDiv");

		invalidateNavBoxes(step);
		break;
		

	default:
		break;
	}

	evt.consume();
}


