var unitprice = 199.00;
var quantity = 1;
var salestax = 0;
var supportqty = 0;
var supportprice; /* set by fn computesupport price */

var subtotal;
var grandtotal;

var discount = null;
var discountcode = '';

var XMLHttpFactories = [
	function () {return new XMLHttpRequest()},
	function () {return new ActiveXObject("Msxml2.XMLHTTP")},
	function () {return new ActiveXObject("Msxml3.XMLHTTP")},
	function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];

function createXMLHTTPObject() {
	var xmlhttp = false;
	for (var i=0, n=XMLHttpFactories.length; i<n; ++i) {
		try {
			xmlhttp = XMLHttpFactories[i]();
		} catch (e) {
			continue;
		}
		break;
	}
	return xmlhttp;
}

function computeinvoice() {
	var taxrow, taxamt, taxrate, unitcell, subcell, grandcell, qtycell;
	var spcell, sqcell, sscell, supportrow, disrow, discell, distitle;
	var rate = salestax;

	taxrow = document.getElementById('taxrow');
	supportrow = document.getElementById('supportrow');
	disrow = document.getElementById('disrow');

	if (rate == 0)
		taxrow.style.visibility = 'hidden';

	if (supportqty == 0)
		supportrow.style.visibility = 'hidden';

	if (!discount)
		disrow.style.visibility = 'hidden';
		
		

	qtycell = document.getElementById('hardqty');
	qtycell.firstChild.data = quantity;

	unitcell = document.getElementById('unitprice');
	unitcell.firstChild.data = '$' + unitprice.toFixed(2);

	subtotal = quantity * unitprice;

	subcell = document.getElementById('subprice');
	subcell.firstChild.data = '$' + subtotal.toFixed(2);

	sqcell = document.getElementById('supportquantity');
	sqcell.firstChild.data = supportqty;

	spcell = document.getElementById('supportprice');
	spcell.firstChild.data = '$' + supportprice.toFixed(2);

	sscell = document.getElementById('supportsubtotal');
	sscell.firstChild.data = '$' + (supportprice * supportqty).toFixed(2);

	subtotal += supportqty * supportprice;

	/* Discount is a function provided by the server via ajax. */
	if (discount) {
		var amt = discount(quantity, supportqty, subtotal);
		if (amt < 0)
			amt = -amt;
		if (subtotal < amt)
			amt = subtotal;

		discell = document.getElementById('discell');
		discell.firstChild.data = '$(' + amt.toFixed(2) + ')';
		distitle = document.getElementById('promcode');
		distitle.firstChild.data = discountcode;

		subtotal -= amt;
	}

	taxrate = document.getElementById('taxrate');
	taxrate.firstChild.data = (100 * rate).toFixed(2) + '%';

	taxamt = document.getElementById('taxamt');
	taxamt.firstChild.data = '$' + (subtotal * rate).toFixed(2);

	grandtotal = (subtotal * (1+rate));
	grandcell = document.getElementById('grandcell');
	grandcell.firstChild.data = '$' + grandtotal.toFixed(2);

	if (rate != 0 && subtotal != 0) {
		try {
			taxrow.style.display = 'table-row';
		} catch (e) {
			taxrow.style.display = '';
		}
		taxrow.style.visibility = 'visible';
	}
	if (supportqty != 0) {
		try {
			supportrow.style.display = 'table-row';
		} catch (e) {
			supportrow.style.display = '';
		}
		supportrow.style.visibility = 'visible';
	}
	if (discount) {
		try {
			disrow.style.display = 'table-row';
		} catch (e) {
			disrow.style.display = '';
		}
		disrow.style.visibility = 'visible';
	}
}

function setcountry(country) {
	var state = document.getElementById('state');
	var i, n;
	var list;

	n = state.length;
	for (i=0; i<n; ++i)
		state.remove(1);

	list = district[country];

	for (var st in list) {
		var opt = document.createElement('option');
		opt.text = st + ' ' + list[st];
		opt.value = st;
		try {
			state.add(opt, null);
		} catch (e) {
			state.add(opt);
		}
	}
	state.selectedIndex = 0;
}


function computesupportprice(qty) {
	if (qty < 3)
		return 149.00;
	if (qty < 5)
		return 141.55;
	if (qty < 11)
		return 134.10;
	if (qty < 21)
		return 126.65;
	return 119.20;
}

function yessupport(ev) {
	supportqty = quantity;
	supportprice = computesupportprice(quantity);
	computeinvoice();
	return true;
}

function nosupport(ev) {
	supportqty = 0;
	supportprice = computesupportprice(quantity);
	computeinvoice();
	return true;
}

function updatelocation(ev) {
	var state = document.getElementById('state').value;
	var country = document.getElementById('country').value;
	var tax = 0;

	if (country == 'US' && state == 'UT')
		tax = 0.0625;
	if (tax != salestax) {
		salestax = tax;
		computeinvoice();
	}
	return true;
}

function updateqty(ev) {
	var q = parseInt(this.value);

	if (isNaN(q) || q<1) {
		this.value = '';
		q = 1;
	}

	if (q != quantity) {
		quantity = q;
		if (supportqty != 0)
			supportqty = q;
		supportprice = computesupportprice(quantity);
		computeinvoice();
	}
	return true;
}

function tocheckout() {
	document.getElementById('cartpage').style.display = 'none';
	document.getElementById('orderpage').style.display = 'none';
	document.getElementById('waiting').style.display = 'none';
	document.getElementById('infopage').style.display = 'block';
	document.getElementById('qty').style.display = 'none';
	document.getElementById('hardqty').style.display = 'inline';

	for (x in defaults) {
		var elt = document.getElementById(x);

		elt.value = defaults[x];
		if (x == 'country' && elt.onchange)
			elt.onchange();
	}

	// So that tax shows up properly if IP detection places the user in Utah.
	updatelocation();

	return false;
}

function towaiting() {
	document.getElementById('cartpage').style.display = 'none';
	document.getElementById('orderpage').style.display = 'none';
	document.getElementById('infopage').style.display = 'none';
	document.getElementById('qty').style.display = 'none';
	document.getElementById('cartgood').style.display = 'none';
	document.getElementById('hardqty').style.display = 'inline';
	document.getElementById('waiting').style.display = 'block';
}


function dectohex(d, padding) {
	var hex = Number(d).toString(16);

	if ((padding===undefined) || padding === null)
		padding = 2;

	while (hex.length < padding)
		hex = '0' + hex;

	return hex;
}

function encode(s) {
	var i, n, x, t = '';

	n = s.length;
	for (i=0; i<n; ++i) {
		x = s.charCodeAt(i);
		if (x < 32)
			t += '\\x' + dectohex(x);
		else if (x < 127)
			t += s.charAt(i);
		else if (x < 256)
			t += '\\x' + dectohex(x);
		else if (x < 0x10000)
			t += '\\u' + dectohex(x, 4);
		else
			t += '\\U' + dectohex(x, 6);
	}
	return t;
}

function tosendorder() {
	var err = false;

	err |= copyvalue('cardtype', true);
	err |= copyvalue('cardnumber', true);

	if (!err) {
		var ty = document.getElementById('cardtype');
		var cc = document.getElementById('cardnumber');
		if (!validcc(cc.value, trim(ty.value))) {
			err = true;
			cc.className = 'missing';
		}
	}

	err |= copyvalue('cardmonth', true);
	err |= copyvalue('cardyear', true);
	err |= copyvalue('cardcode', true);

	if (err) {
		document.getElementById('cartgood').style.display = 'none';
		document.getElementById('infowarn').style.display = 'block';
		return false;
	}

	return sendorder();
}

function sendorder() {
	var post = '';
	var xmlhttp;

	xmlhttp = createXMLHTTPObject();

	if (!xmlhttp)
		return true;

	for (v in order) {
		post += v + ':' + encode(order[v]) + '\n';
	}

	xmlhttp.open("POST", "order.php?ajax=1", true);
	xmlhttp.onreadystatechange =
		function () {
			if (xmlhttp.readyState != 4)
				return;

			if (xmlhttp.status != 200 && status != 0) {
				toerror();
				return;
			}

			/* alert(xmlhttp.responseText); */
			tocomplete(eval('(' + xmlhttp.responseText + ')'));
		}

	towaiting();

	/* alert('post: ' + post); */
	xmlhttp.send(post);
	return false;
}

function todiscount(v) {
	if (v && v.func) {
		discount = v.func;
		computeinvoice();
	}
}

function setdiscount(num) {
	discountcode = num;
}

function sendcoupon(discountcode) {
	if (isNaN(discountcode)) {
		discountcode = 0;
	}
	var xmlhttp;
	var submit = this;
	
	var predefinedValue = false;

	if(discountcode <= 0)
	{
		discountcode = document.getElementById('promotion').value;
	}
	else
	{
		predefinedValue = true;
	}

	submit.value = 'Submitting...';

	xmlhttp = createXMLHTTPObject();
	if (!xmlhttp) {
		alert('You must update to an ajax-capable browser to submit promotion codes');
		return false;
	}

	xmlhttp.open("POST", "coupon.php?promotion=" + discountcode, true);
	xmlhttp.onreadystatechange =
		function () {
			if (xmlhttp.readyState != 4)
				return;

			if (xmlhttp.status != 200 && status != 0) {
				toerror();
				submit.value = 'Apply Coupon';
				return;
			}
			
			if (xmlhttp.responseText == '{ func: null }') {
				// TODO Can we get the database to tell us whether the code expired?
				window.alert('Error: The coupon code "' + discountcode + '" is invalid or expired.');
			} else {
				setdiscount(discountcode);
				if(!predefinedValue)
				{
					window.alert('Code accepted.');
				}
				else
				{
					// If they're coming in from a link with an embedded code.
					tocheckout();
				}
			}

			todiscount(eval('(' + xmlhttp.responseText + ')'));
			submit.value = 'Apply Coupon';
		}

	xmlhttp.send('');
	return false;
}

function trim(s) {
	return s.replace(/^\s+|\s+$/g,"");
}

var order = {};

function copyvalue(id, req) {
	var dst = document.getElementById('e_'+id);
	var src = document.getElementById(id);
	var s = trim(src.value);

	order[id] = s;

	if (dst)
		dst.firstChild.data = src.value;

	if (s.length==0) {
		if (dst)
			dst.style.display = 'none';
		if (req) {
			src.className = 'missing';
			return true;
		}
		return false;
	} else {
		if (dst)
			dst.style.display = 'inline';
		if (req)
			src.className = '';
		return false;
	}
}

function toinvoice() {
	var err = false;

	err |= copyvalue('gname', true);
	err |= copyvalue('fname', true);
	err |= copyvalue('company', false);
	err |= copyvalue('email', true);
	err |= copyvalue('phone', true);
	err |= copyvalue('fax', false);
	err |= copyvalue('address1', true);
	err |= copyvalue('address2', false);
	err |= copyvalue('city', true);
	err |= copyvalue('state', true);
	err |= copyvalue('postcode', true);
	err |= copyvalue('country', true);

	order['qty'] = '' + quantity;
	order['grandtotal'] = '' + grandtotal.toFixed(2);
	order['supportqty'] = '' + supportqty;
	order['promotion'] = discountcode;

	if (err) {
		document.getElementById('cartgood').style.display = 'none';
		document.getElementById('infowarn').style.display = 'block';
		return false;
	} else {
		document.getElementById('infowarn').style.display = 'none';
		document.getElementById('cartgood').style.display = 'block';
	}

	if (grandtotal == 0) {
		return sendorder();
	}

	document.getElementById('cartpage').style.display = 'none';
	document.getElementById('infopage').style.display = 'none';
	document.getElementById('waiting').style.display = 'none';
	document.getElementById('orderpage').style.display = 'block';
	return false;
}

function toerror() {
	document.getElementById('cartgood').style.display = 'none';
	document.getElementById('waiting').style.display = 'none';
	document.getElementById('infowarn').style.display = 'none';
	document.getElementById('infofail').style.display = 'block';
}

function toreject() {
	document.getElementById('cartgood').style.display = 'none';
	document.getElementById('waiting').style.display = 'none';
	document.getElementById('infowarn').style.display = 'none';
	document.getElementById('inforeject').style.display = 'block';
}

function tocomplete(v) {
	var node, serial, token, url, i, n, approve;

	if (v['status'] != 'approved') {
		toreject();
		return;
	}

	node = document.getElementById('fr_license');
	serial = document.getElementById('fr_serial').firstChild;
	token = document.getElementById('fr_token').firstChild;
	url = document.getElementById('fr_url');
	approve = document.getElementById('infoapprove');

	n = v['license'].length;
	for (i=0; i<n; ++i) {
		var newnode;
		serial.data = v['license'][i]['serial'];
		token.data = v['license'][i]['token'];
		url.firstChild.data = v['license'][i]['url'];
		url.href = v['license'][i]['url'];
		newnode = node.cloneNode(true);
		newnode.id = '';
		approve.appendChild(newnode);
	}

	document.getElementById('cartgood').style.display = 'none';
	document.getElementById('waiting').style.display = 'none';
	document.getElementById('infowarn').style.display = 'none';
	approve.style.display = 'block';
}

function isnumberkey(ev) {
	var code;

	if (ev.which === undefined || ev.which != 0) {
		code = ev.keyCode;
	} else code = ev.charCode;

	if (code > 31 && (code < 48 || code > 57))
		return false;
	return true;
}

function validcc(cc, ty) {
	var len;
	var i, n, sum = 0;

	/* eliminate non-digits */
	cc = cc.replace(/[^0-9]/g, '');
	len = n = cc.length;
	for (i=0; i<n; ++i) {
		var c = cc.charAt(n-i-1);
		var k = parseInt(c) * ((i%2)+1);
		sum += k<10? k: (k+1);
	}
	sum = sum % 10;

	switch(ty) {
	case 'amex':
		var t = cc.charAt(0);
		var u = cc.charAt(1);
		return len==15 && t=='3' && sum==0 && (u=='4' || u=='7');
	case 'visa':
		return (len==13 || len==16) && sum==0 && cc.charAt(0)=='4';
	case 'mc':
		k = parseInt(cc.substring(0, 2));
		return len==16 && sum==0 && 51<=k && k<=55;
	case 'discover':
		k = parseInt(cc.substring(0, 4));
		return len==16 && sum==0 && k==6011;
	}

	return false;
}


function bindshop() {
	var cty = document.getElementById('country');
	for (var ct in country) {
		var opt = document.createElement('option');
		opt.text = ct + ' ' + country[ct];
		opt.value = ct;
		try { cty.add(opt, null); } catch (e) { cty.add(opt); }
	}

	document.getElementById('tocheckout').onclick = tocheckout;
	document.getElementById('toinvoice').onclick = toinvoice;
	document.getElementById('sendorder').onclick = tosendorder;
	document.getElementById('applycoupon').onclick = sendcoupon;

	document.getElementById('qty').onchange = updateqty;
	document.getElementById('qty').onkeyup = updateqty;
	document.getElementById('qty').onkeypress = isnumberkey;
	document.getElementById('yessupport').onclick = yessupport;
	document.getElementById('nosupport').onclick = nosupport;

	document.getElementById('state').onchange = updatelocation;

	supportprice = computesupportprice(quantity);
	computeinvoice();
};


if (window.addEventListener)
        window.addEventListener('load', bindshop, false);
else {
        if (!window.onload)
                window.onload = bindshop;
        else {
                var oldload = window.onload;
                window.onload = function(e) {
                        oldload.call(window, e);
                        return bindshop(e);
                };
        }
}


