﻿// Constants. todo: change to const's one day when all browsers support it
var	Csort_by_quantity		= 0,
		Csort_by_price			= 1,
		Csort_by_code			= 2,
		Csort_by_description	= 3,
		Csort_by_total_price	= 4;

var	Csort_sense_ascending	= 0,
		Csort_sense_descending	= 1;

var	Citem_total_field = 1,
		Cquantity_field = 3;

var	g_Total = 0;

// Basket vars
var	g_BasketArray;
var	g_DeliveryOptionsArray;

var	g_SortField = Csort_by_price,
		g_SortSense = Csort_sense_ascending;

// Basket document elements
var	g_BasketTable,
		g_BasketTableBody,
		g_BasketTotalCell;

//		g_DeliveryOptionsTable,
//		g_DeliveryOptionsTableBody;


// Send request to add 1 to a shopping basket item
function	FireIncQ() {
	var	pc = g_BasketArray[ CalcRowOfImage( this, g_BasketTable ) ].m_PartCode;
	StartDownload( FormatIncrementBasketPart(pc), UpdateBasketTableCallback );
}

// Send request to sub 1 from a shopping basket item
function	FireDecQ() {
	var	row = CalcRowOfImage( this, g_BasketTable );
	var	pc = g_BasketArray[ row ].m_PartCode;

	if( g_BasketArray[ row ].m_Quantity > 1 )
		StartDownload( FormatDecrementBasketPart(pc), UpdateBasketTableCallback );
}

// Send request to remove a basket item
function	FireDeleteRow() {
	var	body_rel_row = CalcRowOfImage( this, g_BasketTable );
	StartDownload( FormatDeleteBasketPart(g_BasketArray[ body_rel_row ].m_PartCode), UpdateBasketTableCallback );
}

function quantityChange(ev) {
	var edit = getEventSource(ev);

	if( edit.value != edit.defaultValue ) {
		var num = parseInt(edit.value);
		edit.value = num;
		StartDownload(FormatSetQuantity(edit.m_Index, edit.value), UpdateBasketTableCallback);
	}
}

// Send request to remove all basket items
function	FireDeleteAll() {
	StartDownload( "Basket.asmx/Clear", UpdateBasketTableCallback );
}

// Reset the basket table column header images to be in unsorted state
function	ResetSortImgs() {
	var	cells = g_BasketTable.tHead.rows[ 0 ].cells;

	for( var i = 0; i < cells.length; i++ )
		if( cells[ i ].childNodes[ 0 ] != undefined )
			cells[ i ].childNodes[ 0 ].value = "-";
}

// Convert table column index to const value which is the sort field
function	TableColToSortField( col ) {
	switch( col ) {
		case 1:
			return	Csort_by_total_price;

		case 2:
			return	Csort_by_quantity;

		case 3:
			return	Csort_by_price;

		case 4:
			return	Csort_by_code;

		case 5:
			return	Csort_by_description;

		default:
		break;
	}// switch
}

// Callback for clicking on table column header image
function	SortImgClick() {

	if( this.value != "-" ) {
		if( g_SortSense == Csort_sense_ascending ) {
			this.value	= "▲";
			g_SortSense	= Csort_sense_descending;
		} else {
			this.value	= "▼";
			g_SortSense	= Csort_sense_ascending;
		}
	} else {
		ResetSortImgs();

		g_SortField = TableColToSortField( CalcColOfImage( this ) );

		if( g_SortSense == Csort_sense_ascending )
			this.value	= "▼";
		else
			this.value	= "▲";

	}
	SortBasketAndTable();
}

// Compare the values of a basket field and return a value to impose a relative ordering on the items
function	CmpBasketFields( a, b ) {
	switch( g_SortField )
	{
		case	Csort_by_quantity :
			if( g_SortSense == Csort_sense_ascending )
				return	a.m_Quantity - b.m_Quantity;
			else
				return	b.m_Quantity - a.m_Quantity;
		break;

		case	Csort_by_price :
			if( g_SortSense == Csort_sense_ascending )
				return	a.m_Price - b.m_Price;
			else
				return	b.m_Price - a.m_Price;
		break;

		case	Csort_by_code :
			if( a.m_PartCode == b.m_PartCode )
				return	0;

			if( g_SortSense == Csort_sense_ascending ) {
				if( a.m_PartCode > b.m_PartCode )
					return	1;
				return	-1;
			} else {
				if( a.m_PartCode < b.m_PartCode )
					return	1;
				return	-1;
			}
		break;

		case	Csort_by_description :
			if( a.m_Description == b.m_Description )
				return	0;

			if( g_SortSense == Csort_sense_ascending ) {
				if( a.m_Description > b.m_Description )
					return	1;
				return	-1;
			} else {
				if( a.m_Description < b.m_Description )
					return	1;
				return	-1;
			}
		break;

		case	Csort_by_total_price :
			if( g_SortSense == Csort_sense_ascending )
				return	a.m_Price * a.m_Quantity - b.m_Price * b.m_Quantity;
			else
				return	b.m_Price * b.m_Quantity - a.m_Price * a.m_Quantity;
		break;

		default:
			throw	"Error, bad sort_field: " + sort_field;
		break;
	}// switch
}

// Exchange two items. Swaps the items in the items array and the page table.
function	ExchangeItems( array, i1, i2 ) {
	// exchange the basket_array items
	tmp = array[ i1 ];
	array[ i1 ] = array[ i2 ];
	array[ i2 ] = tmp;

	// exchange the document table rows
	var	r1, r2, r3;

	r1 = g_BasketTable.tBodies[ 0 ].rows[ i1 ]
	r2 = g_BasketTable.tBodies[ 0 ].rows[ i2 ]

	if( i2 == g_BasketTable.tBodies[ 0 ].rows.length - 1 )
		r3 = null;
	else
		r3 = g_BasketTable.tBodies[ 0 ].rows[ i2 + 1 ];

	g_BasketTable.tBodies[ 0 ].insertBefore( r2, r1 );
	g_BasketTable.tBodies[ 0 ].insertBefore( r1, r3 );
}

// Sort just the basket array. We do this on first download when we don't
// have a corresponding table on the page and when we reinitialise the basket
function	SortBasketArray( field ) {
	sort_field = field;

	switch( sort_field )
	{
		case	Csort_by_quantity :
			g_BasketArray.sort(
				function( a, b )
				{ return	a.m_Quantity - b.m_Quantity; }
			);
		break;

		case	Csort_by_price :
			g_BasketArray.sort(
				function( a, b )
				{ return	a.m_Price - b.m_Price; }
			);
		break;

		case	Csort_by_code :
			g_BasketArray.sort(
				function( a, b ) {
					if( a.m_Code == b.m_Code )
						return	0;
					if( a.m_Code < b.m_Code )
						return	1;
					return	-1;
				}
			);
		break;

		case	Csort_by_description :
			g_BasketArray.sort(
				function( a, b ) {
					if( a.m_Description == b.m_Description )
						return	0;
					if( a.m_Description < b.m_Description )
						return	1;
					return	-1;
				}
			);
		break;

		case	Csort_by_total_price :
			g_BasketArray.sort(
				function( a, b )
				{ return	a.m_Price * a.m_Quantity - b.m_Price * b.m_Quantity; }
			);
		break;
	}// switch
}

// Sort the basket and the document table body.
// Assumes that the basket_array and the document table body are congruent.
function	SortBasketAndTable() {
	QuickSort( g_BasketArray, CmpBasketFields, ExchangeItems );
	UpdateTotal();
}

// Find the index of the basket item with part_code
function	FindPartInBasketArray( part_code ) {
	if( part_code != undefined )
		for( var i = 0; i < g_BasketArray.length; i++ )
			if( g_BasketArray[ i ].m_PartCode == part_code )
				return	i;
	return	-1;
}

// Update the order total on the page
function	UpdateTotal() {
	if( g_BasketArray == null || g_BasketArray.length == 0 )
		document.getElementById("OrderButton").disabled = true;

	g_BasketTotalCell.innerHTML = CalcTotal();
}

// Update the total which includes shipping
function 	UpdateTotalTotal() {
	var	dp = GetDeliveryPrice();
	var	tt = g_Total;

	if( tt != 0  ) {
		tt	+= dp;
		tt += tt * g_VatAmount;
	}
	tt = FormatPrice( tt );

	document.getElementById("totalArea").innerHTML = g_CurrencySymbol + " " + tt + "&nbsp; &nbsp; <em>VAT has been added at " + (100 * g_VatAmount) + "%.</em>";
}

function totalOfEssentials() {
	var total = 0;

	for( var i = 0; i < g_BasketArray.length; i++ ) {
		var itm = g_BasketArray[ i ];

		if( itm.m_bEssential )
			total += itm.m_Price * itm.m_Quantity;
	}
	return total;
}

function PreventFreeDeliveryCallback() {
	if( totalOfEssentials() < 70 ) {
		for( var indx = 1; indx < g_DeliveryOptionsArray.length; ++indx ) {
			if( g_DeliveryOptionsArray[ indx ].m_Price == 0 ) {
				var select = document.getElementById( "deliveryOptionSelect" );

				// if we've disabled free del, make sure it's not the selected option
				if( select.selectedIndex == indx - 1)
					select.selectedIndex = 0;
				return;
			}
		}
	}
}

function CanHazFreeDelivery() {
	var freeDelivery = false;

	if( totalOfEssentials() >= 70 )
		freeDelivery = true;

	// find the 0 priced delivery option and dis/enable it
	for( var indx = 1; indx < g_DeliveryOptionsArray.length; ++indx ) {
		if( g_DeliveryOptionsArray[ indx ].m_Price == 0 ) {
			var select = document.getElementById( "deliveryOptionSelect" );

			select.options[ indx - 1 ].disabled = !freeDelivery;

			// automatically select free delivery if eligible
			if( freeDelivery )
				select.selectedIndex = indx - 1;
			else {
				// if we've disabled free del, make sure it's not the selected option
				if( select.selectedIndex == indx - 1)
					select.selectedIndex = 0;
			}
			return;
		}
	}
}

// Scan the delivery options table for the checked delivery option and return price.
function	GetDeliveryPrice() {
	var	select = document.getElementById( "deliveryOptionSelect" );

	if( !select )
		return 0;

	if( true == select.disabled )
		return 0;

	var	selected_op = select.selectedIndex;

	if( selected_op >= 0 && selected_op < g_DeliveryOptionsArray.length - 1 )
		return	g_DeliveryOptionsArray[ 1 + selected_op ].m_Price;
	return	0;
}

// Calculate the price of the items in the basket.
function	CalcTotal() {
	var	i, total = 0, has_unknowns = false;

	if( g_BasketArray && g_BasketArray.length > 0 ) {
		var	has_poas = false;

		for( i = 0; i < g_BasketArray.length; i++ ) {
			if( g_BasketArray[ i ].m_Price == 0 )
				has_poas = true;

			total += g_BasketArray[ i ].m_Price * g_BasketArray[ i ].m_Quantity;
		}

		if( has_poas )
			total = 0;

	}
	g_Total = total;
	return	FormatPrice( total );
}

// Create the basket table header section.
function	CreateBasketHeader() {
	var head	= document.createElement( "THEAD" );
	var row	= document.createElement( "TR" );
	var strs	= new Array( "Remove", "Part Code", "Unit Price ", "Quantity", "Price ", "Description" );
	var cell;

	g_BasketTable	= document.createElement( "TABLE" );
	g_BasketTable.className = "basketTable";

	strs[2] += "(" + g_CurrencySymbol + ")";
	strs[4] += "(" + g_CurrencySymbol + ")";

/*
	var	img;

	// create the sort buttons headers
	for( var i = 0; i < 6; i ++ ) {
		if( i == 0 )
			cell = CreateHeaderCell( "" );
		else {
			if( i == 3 ) // we default to sorting on unit price
				img = CreateButton("▼", SortImgClick);
			else
				img = CreateButton("-", SortImgClick);

			cell = CreateHeaderCell( img );
		}

		if( i == 2 )
			cell.colSpan = 3;

		row.appendChild( cell );
	}

	head.appendChild( row );
*/

	// create the column names
//	row		= document.createElement( "TR" );

	for( var i = 0; i < strs.length; i++ ) {
		cell = CreateHeaderCell( strs[ i ] );
		cell.className = "basketHeader";

//		if( i == 2 )
//			cell.colSpan = 3;

		row.appendChild( cell );
	}

	head.appendChild( row );

	g_BasketTable.appendChild( head );

	var	col_group = document.createElement( "COLGROUP" );

	cell	= document.createElement( "COL" );
	cell.align = "middle";
	col_group.appendChild( cell );

	cell	= document.createElement( "COL" );
	cell.align = "right";
	col_group.appendChild( cell );

	cell	= document.createElement( "COL" );
	cell.align = "right";
	cell.char = ".";
	col_group.appendChild( cell );

	cell	= document.createElement( "COL" );
	cell.align = "right";
	col_group.appendChild( cell );

	cell	= document.createElement( "COL" );
	cell.align = "right";
	cell.char = ".";
	col_group.appendChild( cell );

	g_BasketTable.appendChild( col_group );
}

// Create a basket table row
function	CreateBasketRow( table_body, item, row_num ) {
	var	row	= document.createElement( "TR" );
	var	cell, price, total, new_img;

	if( item.m_bEssential )
		row.className = "ess";

	if( item.m_Price == 0 ) {
		price = "POA";
		total = "POA";
		row.className = "notPriced";
	} else {
		price = item.m_Price.toFixed( 2 );
		total = ( item.m_Price * item.m_Quantity ).toFixed( 2 );
	}

	new_img	= CreateButton("Remove", FireDeleteRow);
	cell	= CreateCell( new_img );
	row.appendChild( cell );

	cell	= CreateCell( item.m_PartCode );
	row.appendChild( cell );

	cell	= CreateCell( price );
	row.appendChild( cell );

	var input = document.createElement("INPUT");
	input.value = input.defaultValue = item.m_Quantity;
	input.m_Index = item.m_Index;
	input.className = "quant";

	AddEventListener(input, "blur", quantityChange);

	cell	= CreateCell( input );
	row.appendChild( cell );

	cell	= CreateCell( total );
	cell.className = "price";
	row.appendChild( cell );

	if( item.m_link ) {
		var	link = document.createElement( "A" );
		link.href = "images/" + item.m_Url;
		link.innerHTML = item.m_Description;
		cell	= CreateCell( link );
	} else
		cell	= CreateCell( Decapitialise( item.m_Description )  );

	row.appendChild( cell );

	g_BasketTableBody.appendChild( row );
}

// Create the basket table footer section
function	CreateBasketFooter() {
	var foot	= document.createElement( "TFOOT" );
	var row	= document.createElement( "TR" );
	var cell, img;

	cell = CreateHeaderCell( CreateButton( "Delete all", FireDeleteAll ) );
	row.appendChild( cell );

	g_BasketTotalCell = CreateHeaderCell( CalcTotal() );
	row.appendChild( g_BasketTotalCell );

	cell = CreateHeaderCell( "Sub total, ex. VAT & shipping" );
	cell.id = "totalCaption";
	cell.colSpan = 6;
	row.appendChild( cell );
	foot.appendChild( row );
	g_BasketTable.appendChild( foot );

	UpdateTotal();
}

// Create a delivery option table row
function	CreateDeliveryOption( delivery_opt, index ) {

	var	optionEntry = document.createElement( "OPTION" );

	optionEntry.text = g_CurrencySymbol + " " + delivery_opt.m_Price + " - " + delivery_opt.m_Description;
	optionEntry.value = index;
	optionEntry.selected = (index == 1);

	return	optionEntry;
}

// Create the delivery options table.
function	CreateDeliveryOptions() {
	var	th_row, cell, p, select;

	cell = document.getElementById( "deliveryOptions" );

	if(g_DeliveryOptionsArray.length == 0 ) {
		cell.innerHTML = "<em>No shipping options are available</em>";
		return;
	}
	// note
	cell = document.getElementById( "deliveryOptionsNote" );

	p = document.createElement( "div" );

	p.innerHTML = g_DeliveryOptionsArray[ 0 ];
	p.style.fontSize = "75%";
	cell.appendChild( p );

	if(g_DeliveryOptionsArray.length == 1)
		return;

	// options
	cell = document.getElementById( "deliveryOptions" );
	select = document.createElement("SELECT");
	select.id = "deliveryOptionSelect";
	select.name = "deliveryOptionSelect";

	AddEventListener( select, "change", PreventFreeDeliveryCallback );
	AddEventListener( select, "change", UpdateTotalTotal );

	if( IsMoz() )
		for( var i = 1; i < g_DeliveryOptionsArray.length; i++ )
			select.add( CreateDeliveryOption( g_DeliveryOptionsArray[ i ], i ), null );
	else
		for( var i = 1; i < g_DeliveryOptionsArray.length; i++ )
			select.add( CreateDeliveryOption( g_DeliveryOptionsArray[ i ], i ) );

	cell.appendChild( select );
}

// Fill the basket table rows
function	PopulateBasketBody() {
	if( g_BasketArray.length == 0 ) {
		var row = document.createElement("TR");
		var cell = document.createElement("TD");
		row.appendChild(cell);
		cell.id = "noItems";
		cell.colSpan = 8;
		cell.innerHTML = "&lt; no items &gt;";
		g_BasketTableBody.appendChild(row);
	}
	else
		for( var i = 0; i < g_BasketArray.length; i++ )
			CreateBasketRow( g_BasketTableBody, g_BasketArray[ i ], i );
}

// Create the shopping basket, called once on page load.
function	CreateBasket() {
	CreateBasketHeader();

	g_BasketTableBody	= document.createElement( "TBODY" );
	g_BasketTable.appendChild( g_BasketTableBody );

	CreateBasketFooter();
}

function	FormatGetBasket() {
	return "Basket.asmx/Get";
}

function 	FormatGetDeliveryOptions2() {
	return "WebSpares.asmx/GetDeliveryOptions2";
}

function	FormatAddPartToBasket( partCode ) {
	return "Basket.asmx/Add?PartCode=" + partCode;
}

function	FormatIncrementBasketPart( partCode ) {
	return FormatAddPartToBasket( partCode );
}

function	FormatDecrementBasketPart( partCode ) {
	return	"Basket.asmx/Subtract?PartCode=" + partCode;
}

function	FormatDeleteBasketPart( partCode ) {
	return	"Basket.asmx/Remove?PartCode=" + partCode;
}

function FormatSetQuantity(index, newQty) {
	return "Basket.asmx/SetQuantity?index=" + index + "&qty=" + newQty;
}

function 	StashDeliveryOptions2() {
	var docEle = g_XmlRequester.responseXML.documentElement;
	var a = new Array();

	StripWhiteSpaceNodes(docEle);

	a.push(getTextContent(docEle.firstChild));

	var ops = docEle.lastChild;

	StripWhiteSpaceNodes(ops);

	for( var i = 0; i < ops.childNodes.length; ++i ) {
		var op = ops.childNodes[ i ];

		StripWhiteSpaceNodes(op);

		var delOp = new DeliveryOption(getTextContent(op.firstChild), parseFloat(getTextContent(op.lastChild)));
		a.push(delOp);
	}
	g_DeliveryOptionsArray = a;
	CreateDeliveryOptions();
}

function	UpdateBasketTableCallback() {
	g_BasketArray = GetBasketFromXmlDoc(g_XmlRequester.responseXML);

	DeleteTableBody( g_BasketTable );

	if( g_BasketArray.length != 0 )
		SortBasketArray( Csort_by_code /*g_SortField*/ );

	if( g_BasketArray.length > 0 )
		document.getElementById("OrderButton").disabled = false;
	else
		document.getElementById("OrderButton").disabled = true;

	UpdateTotal();
	PopulateBasketBody();
	UpdateTotalTotal();
	CanHazFreeDelivery();
}

// On page load initialisation
function	InitBasket() {
	g_BasketArray = new Array();

	CreateBasket();
	document.getElementById( "theBasket" ).appendChild( g_BasketTable );

	StartSynchronousDownload( FormatGetDeliveryOptions2(), StashDeliveryOptions2 );
	StartDownload( FormatGetBasket(), UpdateBasketTableCallback );
}
