var _reg_count = 1;
var ticker_on = false;
var counter = 0;
var units = []
var last_active = -1;

var speed = .2;
var fps = 30;

function print(text)
{
	//document.getElementById('debug').innerHTML = ''+text;
}

function printadd(text)
{
	//document.getElementById('debug').innerHTML += '<br />'+text;
}

function fc_act_fl(id)
{
	var lists = units[id - 1];
	if (lists[1].length > 0)
	{
		var shown = lists[1][0][1];
		lists[1][0][1] = 1 - shown;
		lists[1][0][15] = true;
	}
}

function insert(array, index, value)
{
	var newArray = [];
	for (var i = 0; i < array.length; ++i)
	{
		if (i == index)
		{
			newArray.push(value);
		}
		
		newArray.push(array[i]);
	}
	
	if (array.length == 0)
	{
		newArray.push(value);
	}
	
	return newArray;
}

function fc_act_sh(id)
{
	last_active = id;
	var lists = units[id - 1];
	if (lists[1].length > 0)
	{
		lists[0] = insert(lists[0], 0, lists[1][0]);
		lists[1] = lists[1].slice(1);
	}
}

function fc_act_ni(id)
{
	last_active = id;
	var lists = units[id - 1];
	if (lists[1].length > 0)
	{
		var total = lists[0].length;
		target = parseInt(Math.random() * 7 - 3) + total - 7;
		if (target < 0) target = 0;
		
		lists[0] = insert(lists[0], target, lists[1][0]);
		lists[1] = lists[1].slice(1);
	}
}

function fc_act_co(id)
{
	last_active = id;
	var lists = units[id - 1];
	if (lists[1].length > 0)
	{
		lists[2].push(lists[1][0]);
		lists[1] = lists[1].slice(1);
	}
}

function ensure_active_populated(id)
{
	var lists = units[id - 1];
	var active = lists[1];
	var unknown = lists[0];
	if (active.length == 0 && unknown.length > 0)
	{
		var card = unknown[unknown.length - 1];
		lists[0] = unknown.slice(0, unknown.length - 1);
		lists[1] = [card];
	}
}

function fc_act_un(id)
{
	last_active = id;
	var lists = units[id - 1];
	if (lists[2].length > 0)
	{
		while (lists[1].length > 0)
		{
			lists[0].push(lists[1][0]);
			lists[1] = lists[1].slice(1);
		}
		lists[1].push(lists[2][lists[2].length - 1]);
		lists[2] = lists[2].slice(0, lists[2].length - 1);
	}
}

function fc_act_fc(id)
{
	last_active = id;
	var front_index = document.getElementById('front_' + id).value;
	units[id - 1][5] = front_index;
	units[id - 1][7] = true;
}

function fc_act_bc(id)
{
	last_active = id;
	var back_index = document.getElementById('back_' + id).value;
	units[id - 1][6] = back_index;
	units[id - 1][7] = true;
}

function fc_act_re(id)
{
	last_active = id;
	var t = units[id - 1][6];
	units[id - 1][6] = units[id - 1][5];
	units[id - 1][5] = t;
	units[id - 1][7] = true;
	document.getElementById('column_picker_' + id).innerHTML = gen_column_picker(id);
}

function gen_column_picker(id)
{
	var output = '';
	var data = units[id - 1];
	
	if (data[3])
	{
		var columns = data[4];
		var front = data[5];
		var back = data[6];
		output += '<div>';
		output += 'Front: <select onchange="fc_act_fc('+id+')" id="front_' + id + '">';
		for (var i = 0; i < columns.length; ++i)
		{
			output += '<option value="' + i + '"';
			if (i == front)
			{
				output += ' selected="selected"';
			}
			output += '>' + columns[i] + '</option>';
		}
		output += '</select> ';
		output += 'Back: <select onchange="fc_act_bc('+id+')" id="back_' + id + '">';
		for (var i = 0; i < columns.length; ++i)
		{
			output += '<option value="' + i + '"';
			if (i == back)
			{
				output += ' selected="selected"';
			}
			output += '>' + columns[i] + '</option>';
		}
		output += '</select>';
		output += '</div>';
	}
	
	return output;
}

function fc_act_pb(id)
{
	last_active = id;
	var lists = units[id - 1];
	var list = [];
	
	for (var j = 0; j < 3; ++j)
	{
		for (var i = 0; i < lists[j].length; ++i)
		{
			list.push(lists[j][i]);
		}
		lists[j] = []
	}
	
	lists[0] = list;
}

function shuffle_list(array)
{
	var list = [];
	while (array.length > 0)
	{
		var index = parseInt(Math.random() * array.length);
		list.push(array[index]);
		array.splice(index, 1);
	}
	return list;
}

function fc_act_mu(id)
{
	last_active = id;
	var lists = units[id - 1];

	for (var i = 0; i < lists[1].length; ++i)
	{
		lists[0].push(lists[1][i]);
	}
	
	lists[0] = shuffle_list(lists[0]);
	lists[1] = [];
}

function fc_nav(id)
{
	var output = '';
	output += '<div>';
	
	output += '<div>';
	output += '<button onclick="fc_act_ni(' + id + ')">' + "No ide<u>a</u>" + '</button> ';
	output += '<button onclick="fc_act_sh(' + id + ')">' + "A little <u>s</u>haky" + '</button> ';
	output += '<button onclick="fc_act_co(' + id + ')">' + "Confi<u>d</u>ent" + '</button>';
	output += '<button onclick="fc_act_fl(' + id + ')">' + "<u>F</u>lip card" + '</button>';
	output += '</div>';
	
	output += '<div>';
	output += '<button onclick="fc_act_un(' + id + ')">' + "Take a card <u>b</u>ack" + '</button>';
	output += '<button onclick="fc_act_re(' + id + ')">' + "<u>R</u>everse Drill" + '</button>';
	output += '<button onclick="fc_act_pb(' + id + ')">' + "<u>P</u>ut all cards back" + '</button>';
	output += '<button onclick="fc_act_mu(' + id + ')">' + "Shuffl<u>e</u>" + '</button>';
	output += '</div>';
	
	output += '</div>';
	
	output += '<div id="column_picker_' + id + '">';
	output += gen_column_picker(id);
	output += '</div>';
	
	return output;
}

function fc_keydown(event)
{
	var id = last_active;
	var k = event.which ? event.which : event.keyCode;
	if (k == 65) fc_act_ni(id);
	if (k == 83) fc_act_sh(id);
	if (k == 68) fc_act_co(id);
	if (k == 70) fc_act_fl(id);
	if (k == 66) fc_act_un(id);
	if (k == 82) fc_act_re(id);
	if (k == 80) fc_act_pb(id);
	if (k == 69) fc_act_mu(id);
}


function register_flashcards(evt)
{
	var e = window.event;
	if (e == undefined) e = evt;
	var id = _reg_count;
	var unit_index = id - 1;
	var element = e.target == undefined ? e.srcElement : e.target;
	var parent = undefined;
	if (element.parentNode)
	{
		parent = element.parentNode.parentNode; // IE: parentElement?
	}
	else
	{
		parent = element.parentElement.parentElement;
	}
	
	parent.childNodes[1].innerHTML = '<div id="host'+id+'"></div><div style="text-align:left;" id="debug"></div>';
	
	var card_strings = parent.childNodes[2].innerHTML.split("\n");
	var columns = parent.childNodes[3].innerHTML.split('|');
	var defaultFontSize = parseInt(parent.childNodes[4].innerHTML);
	var uses_columns = true;
	var cards = [];
	for (var i = 0; i < card_strings.length; ++i)
	{
		var card_string = card_strings[i].trim();
		var sides = card_strings[i].split('|');
		if (sides.length > 1)
		{
			uses_columns = sides.length == columns.length && uses_columns;
			
			var scale = 50;
			var card = [
				sides, // sides
				0, // Side showing
				0, // current x
				0, // current y
				0, // target x
				0, // target y
				-1, // bucket (0: todo, 1: active, 2: finished)
				i, // z index (0 is bottom)
				0.0, // real x
				0.0, // real y
				scale, // scale
				scale, // target scale
				parseInt(scale * 300 / 100), // width
				parseInt(scale * defaultFontSize / 100), // font size
				parseInt(scale * 255 / 100), // color
				false];// invalid
			cards.push(card);
		}
	}
	
	if (cards.length == 0)
	{
		window.alert("This flash card set is empty");
		return;
	}
	
	last_active = id;
	document.onkeydown = fc_keydown;
	
	var vspace = 180.0 / cards.length;
	
	units.push([
		shuffle_list(cards), // todo
		[], // active
		[], // finished
		uses_columns, // uses column labels
		columns, // column names
		0, // front side
		1, // back side
		false, // all invalid
		defaultFontSize,
		vspace // vertical spacing between cards
		]);
	
	initialize_html(id);
	
	_reg_count += 1;
	
	if (!ticker_on)
	{
		window.setInterval("do_tick()", parseInt(1000 / fps));
		ticker_on = true;
	}
}

function do_tick()
{
	print('');
	for (var i = 1; i < _reg_count; ++i)
	{
		do_tick_for_unit(i);
	}
	
	counter += 1;
}

function do_tick_for_unit(id)
{
	render_cards(id);
	ensure_active_populated(id);
}

function initialize_html(id)
{
	var output = '';
	output += '<div style="padding:8px;border:1px solid #888;border-radius:8px;" id="round_host_'+id+'">';
	output += '<div style="position:relative;width:500px;height:300px;">';
	output += '<div style="position:absolute;" id="pile_todo_' + id + '"></div>';
	output += '<div style="position:absolute;" id="pile_finished_' + id + '"></div>';
	output += '<div style="position:absolute;" id="pile_active_' + id + '"></div>';
	output += '</div>';
	output += fc_nav(id);
	output += '</div>';
	
	var host = document.getElementById('host' + id);
	host.innerHTML = output;
	
}

function render_cards(id)
{
	for (var i = 0; i < 3; ++i)
	{
		var card_list = units[id - 1][i];
		render_card_pile(card_list, i, id);
	}
	
	units[id - 1][7] = false;
	
	dump_card_data(id);
}

function render_card_pile(card_list, position, id)
{
	var pile_name = 'todo';
	if (position == 1) pile_name = 'active';
	if (position == 2) pile_name = 'finished';
	
	var htmlHost = document.getElementById('pile_' + pile_name + '_' + id);
	
	var any_changes = units[id - 1][7];
	
	for (var i = 0; i < card_list.length; ++i)
	{
		any_changes = update_card(card_list[i], i, position, id) || any_changes;
	}
	
	if (any_changes || card_list.length == 0)
	{
		var output = '';
		for (var j = 0; j < card_list.length; ++j)
		{
			output += render_card(card_list[j], position, id);
		}
		htmlHost.innerHTML = output;
	}
}

function array_tostring(x)
{
	var output = '[';
	for (var i = 0; i < x.length; ++i)
	{
		if (i > 0) output += ', ';
		output += x[i];
	}
	return output+']';
}

function cardlist_tostring(cl)
{
	var output = '[';
	for (var i = 0; i < cl.length; ++i)
	{
		output += '<br />';
		output += '&nbsp;&nbsp;&nbsp;&nbsp;' + array_tostring(cl[i]);
	}
	output += '<br />] ';
	
	return output;
}

function dump_card_data(id)
{
	var card_data = units[id - 1];
	var a = card_data[0];
	var b = card_data[1];
	var c = card_data[2];
	
	printadd(
		counter + '<br />' + 
		cardlist_tostring(a) + 
		cardlist_tostring(b) + 
		cardlist_tostring(c) +
		card_data[3] + '<br />' +
		array_tostring(card_data[4]) + '<br />' +
		card_data[5] + '<br />' + 
		card_data[6] + '<br />' + 
		card_data[7]);
}

var hex_nums = '0123456789abcdef';
function toHex(dec)
{
	return hex_nums[parseInt(dec / 16)] + hex_nums[dec % 16];
}

function render_card(card, position, id)
{
	var show_contents = position == 1;
	var x = card[2];
	var y = card[3];
	var scale = card[10];
	var width = card[12];
	var font = card[13];
	var color = toHex(255 - card[14]);
	var gray = color + color + color;
	
	var left = x - parseInt((width - 150) / 2);
	var top = y - parseInt((width * 3 / 5 - 90) / 2);
	var padding = parseInt(48 * scale / 100);
	var style = 'position:absolute; border-radius:4px; border: 1px solid #'+gray+'; color:#'+gray+'; left:'+left+'px; top:'+top+'px; width:'+width+'px; height:'+parseInt(width * 3 / 5)+'px; background-color:#fff; font-size:'+font+'px; font-weight:bold;';
	var output = '<div style="'+style+'"><div style="padding-top:'+padding+'px;">';
	
	var data = units[id - 1];
	var front_index = data[5];
	var back_index = data[6];
	var is_front = card[1] == 0;
	var index_to_show = is_front ? front_index : back_index;
	var text = card[0][index_to_show];
	output += text;
	output += '</div></div>';
	return output;
}

// TODO: handle with real numbers and push integer coordinates to x and y
// and if the difference <= 1, set to target
function interpolate(current, target, speed)
{
	if (target == current) return target;
	
	var original = current;
	var sign = (target - current) < 0 ? -1 : 1;
	var current = parseInt((current + speed * target) / (1.0 + speed))
	if (current == original)
	{
		current += sign;
	}
	return current;
}

function update_card(card, order, position, id)
{
	var sideA = card[0];
	var sideB = card[1];
	var x = card[2];
	var y = card[3];
	var tx = card[4];
	var ty = card[5];
	var bucket = card[6];
	var z = card[7];
	var rx = card[8];
	var ry = card[9];
	var scale = card[10];
	var tscale = card[11];
	var width = card[12];
	var font = card[13];
	var color = card[14];
	var changes = false;
	var invalid = card[15];
	var data = units[id - 1];
	var defaultFontSize = data[8];
	
	if (x != tx || y != ty)
	{
		x = interpolate(x, tx, speed);
		y = interpolate(y, ty, speed);
		card[2] = x;
		card[3] = y;
		changes = true;
	}
	
	if (invalid)
	{
		card[16] = false;
		changes = true;
	}
	
	if (scale != tscale)
	{
		scale = interpolate(scale, tscale, speed);
		width = parseInt(300 * scale / 100);
		font = parseInt(defaultFontSize * scale / 100);
		color = parseInt(255 * scale / 100);
		changes = true;
		card[10] = scale;
		card[12] = width;
		card[13] = font;
		card[14] = color;
	}
	
	if (z != order)
	{
		card[7] = order;
		changes = true;
	}
	
	if (bucket != position)
	{
		if (bucket > -1 && units[id - 1][bucket].length > 0)
		{
			units[id - 1][bucket][0][15] = true;
		}
		
		bucket = position;
		card[6] = bucket;
		if (bucket == 0)
		{
			var loc = get_card_loc(id, order);
			tx = loc[0];
			ty = loc[1];
			tscale = 50;
		}
		else if (bucket == 1)
		{
			tx = 200;
			ty = 100;
			tscale = 100;
		}
		else if (bucket == 2)
		{
			tx = 380;
			ty = 5 + order * 2;
			tscale = 25;
		}
		card[11] = tscale;
		card[4] = tx;
		card[5] = ty;
		changes = true;
		card[1] = 0;
	}
	
	if (bucket == 0)
	{
		var loc = get_card_loc(id, order);
		var ntx = loc[0];
		var nty = loc[1];
		if (ntx != tx || nty != ty)
		{
			tx = ntx;
			ty = nty;
			card[4] = tx;
			card[5] = ty;
			changes = true;
		}
	}
	
	return changes;
}

function get_card_loc(id, i)
{
	var vspace = units[id - 1][9];
	var hspace = vspace * 3 / 5;
	return [parseInt(i * hspace), parseInt(i * vspace)];
}
