// utility methods
function getSelectionStart(o) {
	var ret = 0;
	if (o.createTextRange) {
		var r = document.selection.createRange().duplicate();
		r.moveEnd('character', o.value.length);
		if (r.text == '') {
			ret = o.value.length;
		} else {
			ret = o.value.lastIndexOf(r.text)
		}
	} else {
		ret = o.selectionStart;
	}
	return ret;
}

function getSelectionEnd(o) {
	var ret = 0;
	if (o.createTextRange) {
		var r = document.selection.createRange().duplicate();
		r.moveStart('character', -o.value.length);
		ret = r.text.length;
	} else {
		ret =  o.selectionEnd;
	}
	return ret;
}
function makeImage(url) {
	var i = new Image();
	i.src = url;
	return i;
}

// The main order manager
OrderTools = function() {
	this.classes = {
		COUNT_NO_FOCUS:		"no-focus",
		COUNT_FOCUSED:		"focus",
		OPTION_HIDDEN:		"hidden",
		OPTION_VISIBLE:		"visible"
	};
	this.tableEnabled = true;
	this.countFieldsHaveErrors = false;
}

OrderTools.prototype.init = function() {
	// loop through the count boxes, and apply the functions
	for(var c = 0; c<colors.length; c++) {
		var color = colors[c];
		for(var s=0; s<styles.length; s++) {
			var style = styles[s];
			
			// Set up the count input
			var input = this.getCountField(style, color);
			this.initCountField(input, style, color, s, c);
		}
	}
	this.initCountField($('scarves'), 'scarves', false);
	
	// fix tab issue in Firefox
	var divs = $$("div#order-section-customer div.row");
	for(var i=0; i<divs.length; i++) {
		divs[i].tabIndex = -1;
	}
	
	// add faded help text to inputs.
	var inputs = $$("div#order-section-customer .text");
	for(var i=0; i<inputs.length; i++) {
		this.initInput(inputs[i]);
	}
	
	// Update table on type changes
	Event.observe("order-type-sample", "change", this.typeChange.bindAsEventListener(this, false));
	Event.observe("order-type-sample", "click", this.typeChange.bindAsEventListener(this, false));
	Event.observe("order-type-normal", "change", this.typeChange.bindAsEventListener(this, true));
	Event.observe("order-type-normal", "click", this.typeChange.bindAsEventListener(this, true));
	
	// form validation
	Event.observe("f-orderform", "submit", this.formSubmit.bindAsEventListener(this));
	
	// add print button
	var div = $$("div#print div.content")[0];
	var p = document.createElement("p");
	p.className = "print-button";
	var b = document.createElement("input");
	b.type = "button";
	b.value = "Print Form";
	Event.observe(b, "click", this.printForm);
	p.appendChild(b);
	div.appendChild(p);
	
	// add print checkbox images
	var labels = $$("div#row-sample span.value label");
	for(var i=0; i<labels.length; i++) {
		var lbl = labels[i];
		var img = document.createElement("img");
		img.src = "img/print-checkbox.png";
		lbl.insertBefore(img, lbl.firstChild);
	}
	
	// hack/fix for IE6
	if(Prototype.Browser.IE) {
		Event.observe(window, "beforeprint", this.ieBeforePrint);
		Event.observe(window, "afterprint", this.ieAfterPrint);
	}
	
	this.updateTotal();
}
OrderTools.prototype.initCountField = function(input, style, color, s_index, c_index) {
	// listening to focus and blur allow us to update the highlight.
	input.observe("focus", this.countFocus.bindAsEventListener(this, style, color, true));
	input.observe("blur", this.countFocus.bindAsEventListener(this, style, color, false));
	// listenting to change allows us to update the total.
	input.observe("change", this.countUpdated.bindAsEventListener(this));
	// the mouse events are part of listening for cursor changes
	input.observe("mouseup", this.countMouseup.bindAsEventListener(this));
	input.observe("click", this.countMouseup.bindAsEventListener(this));
	if(color) {
		// the keyup event is for moving the selection around.
		// It's skipped on the scarves field
		input.observe("keyup", this.countKeyup.bindAsEventListener(this, s_index, c_index));
	} else {
		// for scarves
		input.observe("keyup", this.scarvesCountKeyup.bindAsEventListener(this));
	}
	// disable submit-on-enter
	input.observe("keypress", this.cancelEnter);
	input.observe("keydown", this.cancelEnter);
	// disable autocomplete
	input.setAttribute("autocomplete", "off");
	var cell = Element.extend(input.parentNode);
	input.setStyle({padding: "3px",
					width: ""+cell.getWidth()-6 + "px"});
	cell.setStyle({padding: 0});
}
OrderTools.prototype.initInput = function(input) {
	input.observe("focus", this.inputFocus.bindAsEventListener(this, true));
	input.observe("blur", this.inputFocus.bindAsEventListener(this, false));
	if(input.value == input.defaultValue) {
		input.addClassName("default-value");
	}
}
OrderTools.prototype.forceInt = function(v) {
	var i = parseInt(v);
	if(isNaN(i) || i==0) {
		i = '';
	}
	return i;
}

OrderTools.prototype.countFocus = function(e, style, color, gained) {
	var input = Event.element(e);
	this.updateFocus(input, style, color, gained);
}

OrderTools.prototype.updateFocus = function(input, style, color, gained) {
	if(gained) {
		if(Prototype.Browser.IE) {
			input.setStyle({border: "2px solid Black",
						    padding: "1px"});
		} else if(!Prototype.Browser.Webkit) {
			Element.extend(input.parentNode).setStyle({outline: "3px solid Black",
												   outlineRadius: "4px"});
		}
		input.select();
	} else {
		if(Prototype.Browser.IE) {
			input.setStyle({border: "none",
						    padding: "3px"});
		} else if(!Prototype.Browser.Webkit) {
			Element.extend(input.parentNode).setStyle({outline: "none"});
		}
		this.updateTotal();
	}
}
OrderTools.prototype.selectColumn = function(el, style, focused) {
	this.updateClassName($('style-header-'+style), 'col-focused', focused);
	for(var c=0; c<colors.length; c++) {
		var cell = $('cell-color-'+colors[c]+'-style-'+style);
		if(cell != el.parentNode) {
			this.updateClassName(cell, 'col-focused', focused);
		}
	}
}
OrderTools.prototype.countUpdated = function(e) {
	this.updateTotal();
}
OrderTools.prototype.countHorizontalMoveCounter = 0;
OrderTools.prototype.countMouseup = function(e) {
	this.updateCursor(Event.element(e));
}
OrderTools.prototype.countKeyup = function(e, styleIndex, colorIndex) {
	var cancel = false;
	var elToFocus = null;
	// save for focus changes in IE
	var oldStyle = styles[styleIndex];
	var oldColor = colors[colorIndex];
	switch(e.keyCode) {
		case Event.KEY_UP:
			colorIndex--;
			if(colorIndex < 0) {
				colorIndex = colors.length-1;
			}
			elToFocus = this.getCountField(styles[styleIndex], colors[colorIndex]);
			break;
		case Event.KEY_DOWN:
			colorIndex++;
			if(colorIndex >= colors.length) {
				colorIndex = 0;
			}
			elToFocus = this.getCountField(styles[styleIndex], colors[colorIndex]);
			break;
		case Event.KEY_LEFT:
			if(this.countHorizontalMoveCounter == -1 || Event.element(e).value.length==0) {
				styleIndex--;
				if(styleIndex < 0) {
					styleIndex = styles.length-1;
				}
				elToFocus = this.getCountField(styles[styleIndex], colors[colorIndex]);
			}
			break;
		case Event.KEY_RIGHT:
			if(this.countHorizontalMoveCounter == 1 || Event.element(e).value.length==0) {
				styleIndex++;
				if(styleIndex >= styles.length) {
					styleIndex = 0;
				}
				elToFocus = this.getCountField(styles[styleIndex], colors[colorIndex]);
			}
			break;
		case Event.KEY_TAB:
			break;
		case Event.KEY_RETURN:
			// on ENTER, act as a TAB - except wrap to beginning of table
			styleIndex++;
			if(styleIndex >= styles.length) {
				styleIndex = 0;
				colorIndex++;
				if(colorIndex >= colors.length) {
					colorIndex = 0;
				}
			}
			elToFocus = this.getCountField(styles[styleIndex], colors[colorIndex]);
			break;
		default:
			this.updateTotal();
	}
	if(elToFocus == null) {
		this.updateCursor(Event.element(e));
	} else {
		this.countHorizontalMoveCounter = 0;
		elToFocus.focus();
		cancel = true;
	}
	if(cancel) {
		Event.stop(e);
	}
}
OrderTools.prototype.scarvesCountKeyup = function(e) {
	switch(e.keyCode) {
		case Event.KEY_TAB:
			break;
		default:
			this.updateTotal();
	}
}
OrderTools.prototype.cancelEnter = function(e) {
	if(e.keyCode == Event.KEY_RETURN) {
		Event.stop(e);
	}
}
OrderTools.prototype.updateCursor = function(input) {
	this.countHorizontalMoveCounter = 0;
	var s = getSelectionStart(input);
	var e = getSelectionEnd(input);
	if(s == e) {
		if(e == 0) {
			this.countHorizontalMoveCounter = -1;
		} else if(e == input.value.length) {
			this.countHorizontalMoveCounter = 1;
		}
	}
}

OrderTools.prototype.formSubmit = function(e) {
	// validation - check for empty fields
	var valid = !this.countFieldsHaveErrors;
	// clear empty fields while we're at it
	var inputs = $$("div#order-section-customer .text");
	for(var i=0; i<inputs.length; i++) {
		var input = inputs[i];
		if(input.value == input.defaultValue) {
			input.value = "";
		}
		if(input.hasClassName("required")) {
			if(!this.validateNotEmpty(input.value)) {
				valid = false;
				input.addClassName("invalid");
			} else {
				input.removeClassName("invalid");
			}
		}
		if(input.id == "email") {
			input.removeClassName("invalid");
			if(input.value != "") {
				if(!/\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/.test(input.value)) {
					valid = false;
					input.addClassName("invalid");
				}
			}
		}
	}
	
	if(!valid) {
		// restore empty fields
		for(var i=0; i<inputs.length; i++) {
			var input = inputs[i];
			if(input.value == '' && !input.hasClassName("invalid")) {
				input.value = input.defaultValue;
			}
		}
		alert("There were problems with your submission.  Please fixed the marked fields.");
		Event.stop(e);
	} else {
		// TODO: save form values in a cookie
	}
}
OrderTools.prototype.validateNotEmpty = function(value) {
	return value != '';
}

OrderTools.prototype.inputFocus = function(e, gained) {
	var input = Event.element(e);
	if(gained) {
		if(input.value == input.defaultValue) {
			input.value = '';
		}
		input.removeClassName("default-value");
	} else {
		if(input.value == '') {
			input.value = input.defaultValue;
			input.addClassName("default-value");
		}
	}
}

OrderTools.prototype.typeChange = function(e, en) {
	this.tableEnabled = en;
	this.updateClassName($("t-choices"), "disabled", !this.tableEnabled);
	var color, style, input;
	for(var c = 0; c<colors.length; c++) {
		color = colors[c];
		for(var s=0; s<styles.length; s++) {
			style = styles[s];
			input = this.getCountField(style, color);
			input.disabled = !this.tableEnabled;
		}
	}
}

OrderTools.prototype.updateTotal = function() {
	var total = 0;
	var color, style, input, val;
	this.countFieldsHaveErrors = false;
	for(var c = 0; c<colors.length; c++) {
		color = colors[c];
		for(var s=0; s<styles.length; s++) {
			style = styles[s];
			input = this.getCountField(style, color);
			total += this.getCountOnField(input);
		}
	}
	var scarvesCount = this.getCountOnField($('scarves'));
	$('totalnumber-value').innerHTML = total + scarvesCount;
	total = (total * costEach) + (scarvesCount * scarfCostEach);
	$('totalcost-value').innerHTML = '$'+total.toFixed(2);
}
OrderTools.prototype.getCountOnField = function(input) {
	val = input.value;
	if(val == '') {
		val = 0;
	} else {
		val = parseInt(val);
	}
	if(!isNaN(val)) {
		input.removeClassName("error");
	} else {
		input.addClassName("error");
		this.countFieldsHaveErrors = true;
		val = 0;
	}
	return val;
}

OrderTools.prototype.printForm = function() {
	var inputs = $$("div#order-section-customer .text");
	for(var i=0; i<inputs.length; i++) {
		var input = inputs[i];
		if(input.value == input.defaultValue) {
			input.value = "";
		}
	}
	window.print();
	for(var i=0; i<inputs.length; i++) {
		var input = inputs[i];
		if(input.value == "") {
			input.value = input.defaultValue;
			input.addClassName("default-value");
		}
	}
}

OrderTools.prototype.ieBeforePrint = function() {
	var inputs = $$("div#order-section-customer .text");
	for(var i=0; i<inputs.length; i++) {
		var input = inputs[i];
		if(input.value == input.defaultValue) {
			input.value = "";
		}
	}
}


OrderTools.prototype.ieAfterPrint = function() {
	var inputs = $$("div#order-section-customer .text");
	for(var i=0; i<inputs.length; i++) {
		var input = inputs[i];
		if(input.value == "") {
			input.value = input.defaultValue;
			input.addClassName("default-value");
		}
	}
}
OrderTools.prototype.getCountField = function(style, color) {
	return $("color-"+color+"-style-"+style);
}
OrderTools.prototype.getRow = function(color) {
	return $("row-color-"+color);
}

OrderTools.prototype.updateClassName = function(el, cn, add) {
	add ? el.addClassName(cn) : el.removeClassName(cn);
}

orderTools = new OrderTools();

// set up the document since we know JavaScript is available.
Event.observe(document, "dom:loaded", orderTools.init.bindAsEventListener(orderTools));
