// calculation functions

function getValue(id) {
	var element = document.getElementById(id);
	if (element == null) { alert('bad id: ' + id); } // MAKE THIS BETTER
	return parseFloat(element.value);
}

function setValue(id, value) {
	var element = document.getElementById(id);
	element.value = value;
}

function setHTML(id, value) {
	var element = document.getElementById(id);
	element.innerHTML = value;
}

function getChipValues() { // returns an array of the current chip values
	return new Array(getValue('white-chip'), getValue('red-chip'), getValue('blue-chip'), getValue('green-chip'), getValue('black-chip'));
}

function getChips() { // returns an array of the current numbers of chips in the set
	return new Array(getValue('white-in-set'), getValue('red-in-set'), getValue('blue-in-set'), getValue('green-in-set'), getValue('black-in-set'));
}

function getRealChips() {
	var players = getValue('players');
	var reserved = getValue('reserved');
	var total_buyins = players + reserved;
	var chips = getChips();
	
	// work out real amount of chips that can be divided
	var i;
	var real_chips = new Array();
	for (i in chips) {
		real_chips[i] = Math.floor(chips[i] / total_buyins) * total_buyins;
	}
	return real_chips;
}

function getMaximumTotal() { // returns the maximum chip total possible per player / buy-in
	
	// get the various values
	var players = getValue('players');
	var reserved = getValue('reserved');
	var chip_values = getChipValues();
	var chips = getRealChips();
	
	// find out the total value of chips available in the set
	var running_total = 0;
	var i;
	for (i in chip_values) {
		running_total += chips[i] * chip_values[i];
	}
	
	// divide between players
	var final_total = Math.round(running_total / (players + reserved));
	
	// make sure it divides right!
	// make sure this divides properly
	var divided = (final_total / chip_values[0]);
	divided = chip_values[0] * Math.floor(divided);
	if (divided < final_total) {
		final_total = divided;
	}
	
	return final_total;
}

function assessTotal() { // this function runs when the user has changed values which might change the maximum total
	
	// get values
	var current_max = getValue('chips-max');
	var actual_max = getMaximumTotal();
	var chip_values = getChipValues();
	var is_new = false;
	
	// make sure it's not more than the chips available
	if (current_max > actual_max) {
		current_max = actual_max;
		is_new = true;
	}
	
	// make sure this divides properly
	var divided = (current_max / chip_values[0]);
	divided = chip_values[0] * Math.floor(divided);
	if (divided < current_max) {
		current_max = divided;
		is_new = true;
	}
	
	if (is_new) {
		setValue('chips-max', current_max);
	}
	
}

// main function

function calculateChips() {
	
	// make sure the total is acceptable
	assessTotal();
	
	// get relevant values
	var players = getValue('players');
	var buyin = getValue('buy-in');
	var reserved = getValue('reserved');
	var total_buyins = players + reserved;
	
	var chip_values = getChipValues();
	var chips = getChips();
	
	var actual_max = getMaximumTotal();
	var max = getValue('chips-max');
		
	// divide up the chips based on the maximum value
	var i;
	var needs = new Array();
	for (i in chips) {
		needs[i] = Math.floor(chips[i] / total_buyins);
	}
	
	// reduce chips until we've got to the right amount
	if (max < actual_max) {
	
		var diff = actual_max - max;
		var end = false;
		
		while (diff != 0) {
			var count = 0
			for(var i=4; i>=0; i--) {
				if (count == 5) {
					alert("Unstable diff: " + diff);
					end = true;
					break;
				}
				if (((diff - chip_values[i]) < 0) || needs[i] == 0) {
					count ++;
					continue;
				}
				diff -= chip_values[i];
				needs[i]--;
				if (diff == 0) {
					end = true;
					break;
				}
			}
			if (end == true) { break; }
		}
		
	}
	
	// work out the monetary value
	var per_unit = buyin / max;
	var cash_values = new Array();
	for (var i in chip_values) {
		cash_values[i] = per_unit * chip_values[i];
		cash_values[i] = cash_values[i].toFixed(2);
	}
	
	// output the values
	setHTML('needs-white', needs[0]);
	setHTML('needs-red', needs[1]);
	setHTML('needs-blue', needs[2]);
	setHTML('needs-green', needs[3]);
	setHTML('needs-black', needs[4]);
	
	setHTML('value-white', cash_values[0]);
	setHTML('value-red', cash_values[1]);
	setHTML('value-blue', cash_values[2]);
	setHTML('value-green', cash_values[3]);
	setHTML('value-black', cash_values[4]);

}

// storage engine

function storeAll() {

	if (typeof JSON == "undefined") {
		return false;
	}

	// set up the storage object
	var to_store = new Object();
	
	// get the relevant data
	to_store.players = getValue('players');
	to_store.buyin = getValue('buy-in');
	to_store.reserved = getValue('reserved');
	to_store.max = getValue('chips-max');
	
	to_store.chip_values = getChipValues()
	to_store.chips = getChips();
	
	// stick all relevant values into an object
	localStorage.setItem('storage', JSON.stringify(to_store));
	
}

function setAll() {

	if (typeof JSON == "undefined") {
		return false;
	}

	// if there's no object, store the defaults
	if (localStorage.getItem('storage') == null) {
		storeAll();	
	}
	
	// retrieve the stored object
	var retrieved = JSON.parse(localStorage.getItem('storage'));
		
	// output the values
	setValue('players', retrieved.players);
	setValue('buy-in', retrieved.buyin);
	setValue('reserved', retrieved.reserved);
	setValue('chips-max', retrieved.max);
	
	setValue('white-in-set', retrieved.chips[0]);
	setValue('red-in-set', retrieved.chips[1]);
	setValue('blue-in-set', retrieved.chips[2]);
	setValue('green-in-set', retrieved.chips[3]);
	setValue('black-in-set', retrieved.chips[4]);
	
	setValue('white-chip', retrieved.chip_values[0]);
	setValue('red-chip', retrieved.chip_values[1]);
	setValue('blue-chip', retrieved.chip_values[2]);
	setValue('green-chip', retrieved.chip_values[3]);
	setValue('black-chip', retrieved.chip_values[4]);
	
	calculateChips();
	
}

// what to do when a field is changed

function assessInputChange(element) {

	// check that the input is fine, otherwise reset everything
	if (element.value != parseFloat(element.value) || element.value < 0) {
		setAll();
		return false;
	}
	
	calculateChips();
	
	// save everything
	storeAll();
}

// initialise script

window.onload=function(){
	
	// run first
	setAll(); 				// this sets everything to the details in local storage
	calculateChips();		// calculates everything for the first time
  
	// bind functionality
	var inputs = document.getElementsByTagName("input");
	var forms = document.getElementsByTagName("form");
	
	// bind functions to input fields
	for (var i=0; i<inputs.length; i++) {
	
		// recalculate if input has been changed
		inputs[i].onblur = function() { assessInputChange(this); }
		
		// automatically select text in input fields
		inputs[i].onfocus = function() { this.select(); }
		
		// stop opera from being so bloody clever about number inputs
		if (window.opera) {
			inputs[i].setAttribute("type", "text");
		}
	}
	
	// stop form submission from working, and remove focus from elements if this happens (for iOS devices)
	for (var i=0; i<forms.length; i++) {
		forms[i].onsubmit = function() {
			for (var i=0; i<inputs.length; i++) {
				inputs[i].blur();
			}
			return false;
		}
	}
}

