// State constants
state_pause_with_lights_on = 0;
state_pause_for_next_subletter = 1;
state_pause_for_next_letter = 2;
state_pause_for_next_word = 3;
state_pause_for_input = 4;

// These are the pause times (in seconds) for the above states
delays = new Array(1, 0.25, 1, 3, 15);

// These are used for debug output
state_strings = new Array("lights on", "next subletter", "next letter", "next word", "input");



initialized = false;
ready_for_input = true;


// DOM objects we'll be referencing frequently
lights = new Array(null, null, null, null, null);
switch_light = null;
switches = new Array(null, null, null, null, null);

// Our timer object
timer = null;


// shepherds frien
sequence0 = new Array(
	new Array(
		new Array(new Array(0.10, 0.10, 0.10, 0.10, 0.10), new Array(0.10, 0.10, 0.10, 0.10, 0.10), new Array(0.10, 0.10, 0.10, 0.10, 0.10), new Array(0.10, 0.10, 0.10, 0.10, 0.10), new Array(0.10, 0.10, 0.10, 0.10, 0.10))
		),

	new Array(
		new Array(new Array(1, 0, 0, 1, 1)), // s
		new Array(new Array(0, 1, 0, 0, 0)), // h
		new Array(new Array(0, 0, 1, 0, 1)), // e
		new Array(new Array(1, 0, 0, 0, 0)), // p
		new Array(new Array(0, 1, 0, 0, 0)), // h
		new Array(new Array(0, 0, 1, 0, 1)), // e
		new Array(new Array(1, 0, 0, 1, 0)), // r
		new Array(new Array(0, 0, 1, 0, 0)), // d
		new Array(new Array(1, 0, 0, 1, 1)) // s
		),

	new Array(
		new Array(new Array(0, 0, 1, 1, 0)), // f
		new Array(new Array(1, 0, 0, 1, 0)), // r
		new Array(new Array(0, 1, 0, 0, 1)), // i
		new Array(new Array(0, 0, 1, 0, 1)), // e
		new Array(new Array(0, 1, 1, 1, 0)) // n
		)
	);


// caffebed
sequence1 = new Array(
	new Array(
		new Array(new Array(0.10, 0.10, 0.10, 0.10), new Array(0.10, 0.10, 0.10, 0.10), new Array(0.10, 0.10, 0.10, 0.10), new Array(0.10, 0.10, 0.10, 0.10), new Array(0.10, 0.10, 0.10, 0.10))
		),

	new Array(
		new Array(new Array(1, 1, 0, 0)), // c
		new Array(new Array(1, 0, 1, 0)), // a
		new Array(new Array(1, 1, 1, 1)), // f
		new Array(new Array(1, 1, 1, 0)) // e
		),
	
	new Array(
		new Array(new Array(1, 0, 1, 1)), // b
		new Array(new Array(1, 1, 1, 0)), // e
		new Array(new Array(1, 1, 0, 1)) // d
		)
	);


// instar
sequence2 = new Array(
	new Array(
		new Array(new Array(0.10, 0.10, 0.10), new Array(0.10, 0.10, 0.10), new Array(0.10, 0.10, 0.10), new Array(0.10, 0.10, 0.10), new Array(0.10, 0.10, 0.10))
		),

	new Array(
		new Array(new Array(1, 0, 0), new Array(0, 1, 0), new Array(1, 0, 0)), // i
		new Array(new Array(0, 0, 0), new Array(0, 1, 0), new Array(1, 0, 1)), // n
		new Array(new Array(0, 0, 0), new Array(1, 1, 0), new Array(0, 0, 1)), // s
		new Array(new Array(1, 1, 0), new Array(0, 1, 0), new Array(0, 0, 0)), // t
		new Array(new Array(0, 0, 0), new Array(0, 1, 0), new Array(1, 1, 0)), // a
		new Array(new Array(0, 0, 0), new Array(1, 1, 1), new Array(0, 0, 0)) // r
		)
	);


// psicrysta
sequence3 = new Array(
	new Array(
		new Array(new Array(0.10, 0.10), new Array(0.10, 0.10), new Array(0.10, 0.10), new Array(0.10, 0.10), new Array(0.10, 0.10))
		),
	
	new Array(
		new Array(new Array(1, 1), new Array(1, 0), new Array(1, 0)), // p
		new Array(new Array(0, 1), new Array(1, 0), new Array(1, 0)), // s
		new Array(new Array(0, 1), new Array(1, 0), new Array(0, 0)), // i
		new Array(new Array(1, 1), new Array(0, 0), new Array(0, 0)), // c
		new Array(new Array(1, 0), new Array(1, 1), new Array(1, 0)), // r
		new Array(new Array(1, 1), new Array(0, 1), new Array(1, 1)), // y
		new Array(new Array(0, 1), new Array(1, 0), new Array(1, 0)), // s
		new Array(new Array(0, 1), new Array(1, 1), new Array(1, 0)), // t
		new Array(new Array(1, 0), new Array(0, 0), new Array(0, 0)) // a
		)
	);


// hypercok
sequence4 = new Array(
	new Array(
		new Array(new Array(0.10, 0), new Array(0.10, 0), new Array(0.10, 0), new Array(0.10, 0), new Array(0.10, 0))
		),
	
	new Array(
		new Array(new Array(0.5, 0), new Array(0.5, 0), new Array(0.5, 0), new Array(0.5, 0)), // h
		new Array(new Array(2.0, 0), new Array(0.5, 0), new Array(2.0, 0), new Array(2.0, 0)), // y
		new Array(new Array(0.5, 0), new Array(2.0, 0), new Array(2.0, 0), new Array(0.5, 0)), // p
		new Array(new Array(0.5, 0)), // e
		new Array(new Array(0.5, 0), new Array(2.0, 0), new Array(0.5, 0)), // r
		new Array(new Array(2.0, 0), new Array(0.5, 0), new Array(2.0, 0), new Array(0.5, 0)), // c
		new Array(new Array(2.0, 0), new Array(2.0, 0), new Array(2.0, 0)), // o
		new Array(new Array(2.0, 0), new Array(0.5, 0), new Array(2.0, 0)) // k
		)
	);



sequences = new Array(
	sequence0,
	sequence1,
	sequence2,
	sequence3,
	sequence4
	);


answers = new Array(
	new Array(new Array(0, 0, 1, 0, 0)), // d
	new Array(new Array(1, 0, 1, 0, 0)), // a
	new Array(new Array(0, 0, 1, 0, 0), new Array(0, 1, 0, 0, 0), new Array(0, 0, 1, 0, 0)), // x
	new Array(new Array(1, 0, 0, 0, 0), new Array(1, 0, 0, 0, 0), new Array(1, 0, 0, 0, 0)), // l
	new Array(new Array(1, 0, 0, 0, 0)) // e
	);


// This holds the answer the the user is currently submitting
user_answer = null;

sequence_marker = 0;
word_marker = 0;
letter_marker = 0;
subletter_marker = 0;

// This is set when the user has asked to jump to the beginning of an
// arbitrary sequence.
sequence_override = -1;


function ShowState(state, delay)
{
	document.getElementById("db_state").innerText = state;
	document.getElementById("db_delay").innerText = delay;
	document.getElementById("db_sequence").innerText = sequence_marker;
	document.getElementById("db_word").innerText = word_marker;
	document.getElementById("db_letter").innerText = letter_marker;
	document.getElementById("db_subletter").innerText = subletter_marker;
}


function InitBlinky()
{
	for(i = 0; i < lights.length; i++)
		lights[i] = document.getElementById("light" + i);

	switch_light = document.getElementById("switch_light");

	for(i = 0; i < switches.length; i++)
		switches[i] = document.getElementById("switch" + i);

	initialized = true;
	
	ShowState("init", 0);
}

function TurnOnLight(light)
{
	light.src = "on.gif";
}

function TurnOffLight(light)
{
	light.src = "off.gif";
}

function TurnOffAllLights()
{
	for(i = 0; i < lights.length; i++)
		TurnOffLight(lights[i]);
}

function ShowCurrentLights()
{
//	window.status = ("ShowCurrentLights(): " + sequence_marker + ", " + letter_marker + ", " + subletter_marker);
	
	multiplier = 0
	
	sequence = sequences[sequence_marker];
	word = sequence[word_marker];
	letter = word[letter_marker];
	subletter = letter[subletter_marker];

	for(i = 0; i < lights.length; i++)
		{
		if(i < subletter.length && subletter[i])
			{
			if(subletter[i] > multiplier)
				multiplier = subletter[i];

			TurnOnLight(lights[i]);
			}
		else
			TurnOffLight(lights[i]);
		}

	if(multiplier == 0)
		multiplier = 1;

	return multiplier;
}

function AdvanceLights()
{
	new_state = state_pause_for_next_subletter;

	// Get our current location in the sequence
	sequence = sequences[sequence_marker];
	word = sequence[word_marker];
	letter = word[letter_marker];
	subletter = letter[subletter_marker];

	// Advance the subletter.
	subletter_marker++;
	if(subletter_marker >= letter.length)
		{
		// If we've done the last subletter, advance the letter
		new_state = state_pause_for_next_letter;
		subletter_marker = 0;
		letter_marker++;
		
		if(letter_marker >= word.length)
			{
			// If we've done the last letter, advance the word
			new_state = state_pause_for_next_word;
			letter_marker = 0;
			word_marker++;
			
			if(word_marker >= sequence.length)
				{
				// If we've done the last word, wait for input
				new_state = state_pause_for_input;
				word_marker = 0;
				}
			}
		}

	// document.write(sequence_marker + ',' + letter_marker + ',' + subletter_marker);

	return new_state;
}

function AdvanceAndBlink()
{
	if(sequence_override >= 0)
		{
		sequence_marker = sequence_override;
		word_marker = 0;
		letter_marker = 0;
		subletter_marker = 0;
		
		sequence_override = -1;
		
		state = state_pause_with_lights_on;
		}
	else
		state = AdvanceLights();
	
	if(state == state_pause_for_input)
		{
		TurnOnLight(switch_light);
		EnableInput();
		}

	TurnOffAllLights();

	delay = delays[state];

	ShowState(state_strings[state], delay);

	timer = setInterval("BlinkAndAdvance()", delay * 1000);
}

function BlinkAndAdvance()
{
	if(timer != null)
		{
		clearInterval(timer);
		timer = null;
		}

	if(InputEnabled())
		DisableInput();

	delay_multiplier = ShowCurrentLights();
	delay = delays[state_pause_with_lights_on] * delay_multiplier;

	ShowState(state_strings[state_pause_with_lights_on], delay);

	setTimeout("AdvanceAndBlink()", delay * 1000);
}

function EnableInput()
{
	user_answer = new Array();
	TurnOnLight(switch_light);
	ready_for_input = true;
}

function DisableInput()
{
	ready_for_input = false;
	TurnOffLight(switch_light);
	user_answer = null;
}

function InputEnabled()
{
	return ready_for_input;
}

function AcceptInput()
{
	if(!initialized)
		{
		InitBlinky();
		BlinkAndAdvance();
		return true;
		}

	if(!InputEnabled())
		return true;

	correct = false;

	new_input = new Array(0, 0, 0, 0, 0);
	for(i = 0; i < switches.length; i++)
		{
		if(switches[i].checked)
			new_input[i] = 1;
		}
	
	user_answer.push(new_input);
	
	correct_answer = answers[sequence_marker];

	if(user_answer.length == correct_answer.length)
		{
		correct = true;
		
		for(i = 0; i < correct_answer.length; i++)
			{
			user_input = user_answer[i];
			correct_input = correct_answer[i];

			for(j = 0; j < correct_input.length; j++)
				{
				if(user_input[j] != correct_input[j])
					{
					correct = false;
					break;
					}
				}
			}
	
		// If the correct answer was given, advance to the next sequence
		if(correct)
			{
			sequence_marker++;
			if(sequence_marker >= sequences.length)
				sequence_marker = 0;
			
			// This is actually kind of redundant, but what the hell.
			word_marker = 0;
			letter_marker = 0;
			subletter_marker = 0;

			// Start the sequence again
			if(timer != null)
				{
				clearInterval(timer);
				timer = null;
				}
			
			BlinkAndAdvance();
			}
		}
}


function JumpToSequence()
{
	sequence_box = document.getElementById("sequence_override");
	new_sequence = sequence_box.value;
	
	if(new_sequence >= 0 && new_sequence < sequences.length)
		sequence_override = new_sequence;
	else
		sequence_box.value = 0;
}