// DOM Constants
var ELEMENT_NODE                = 1;
var ATTRIBUTE_NODE              = 2;
var TEXT_NODE                   = 3;
var CDATA_SECTION_NODE          = 4;
var ENTITY_REFERENCE_NODE       = 5;
var ENTITY_NODE                 = 6;
var PROCESSING_INSTRUCTION_NODE = 7;
var COMMENT_NODE                = 8;
var DOCUMENT_NODE               = 9;
var DOCUMENT_TYPE_NODE          = 10;
var DOCUMENT_FRAGMENT_NODE      = 11;
var NOTATION_NODE               = 12;

function Address()
{
    this.address1 = "";
    this.address2 = "";
    this.town = "";
    this.county = "";
    this.country = "";
    this.postcode = "";
}

Address.prototype.toString = function()
{
    return this.address1 + ", " + this.address2 + ", " + this.town + ", " + this.county + ", " + this.country + ", " + this.postcode;
}

Address.prototype.shortAddress = function()
{
    if (this.address2 != null && this.address2.length > 0)
        return this.address1 + ", " + this.address2 + ", " + this.town;
    else
        return this.address1 + ", " + this.town;;
}


var req = null;
var popup = null;
var selectBox = null;
var addresses = null;
var formName = null;

function getFormElement(fieldName)
{
	return document.getElementById(formName + fieldName);
}

function initAddressLookup()
{
    selectBox = document.getElementById("select-box");
}

function load(url)
{
    if (window.XMLHttpRequest)
    {
        req = new XMLHttpRequest();
        req.onreadystatechange = processReqChange;
        req.open("GET", url, true);
        req.send(null);
    }
    else if (window.ActiveXObject)
    {
        req = new ActiveXObject("Microsoft.XMLHTTP");
        if (req)
        {
            req.onreadystatechange = processReqChange;
            req.open("GET", url, true);
            req.send();
        }
    }
}

function processReqChange()
{
    if (req.readyState == 4) // Complete
    {
        if (req.status == 200) // OK
        {
            var response  = req.responseXML.documentElement;
            addresses = deSerializeAddresses(response);
            populateSelectBox(addresses);
        }
        else
        {
            alert("There was a problem retrieving the XML data:\n" + req.statusText);
        }
    }
}

function populateSelectBox(addresses)
{
    var html = "";

    if (addresses == null || addresses.length < 1)
    {
        html = "<option>No addresses found</option>"
    }
    else
    {
        for (var i = 0; i < addresses.length; i++)
        {
            html += "<option value=\"" + i + "\">" + addresses[i].shortAddress() + "</option>";
        }
    }

    html = "<select id=\"addresses\" onchange=\"javascript:selectAddress()\" size=\"6\">" + html + "</select>";
    html = "<label>Please select your address</label>" + html;
    selectBox.innerHTML = html;
}

function selectAddress()
{
    var selectBox = document.getElementById("addresses");
    var index = selectBox.options[selectBox.selectedIndex].value;
    var properties = new Array("address1", "address2", "town", "county", "postcode");
    var fields = new Array("address1", "address2", "city", "county", "postcode");
    var address = addresses[index];

    for (var i = 0; i < fields.length; i++)
    {
        getFormElement(fields[i]).value = address[properties[i]];
    }
}

function deSerializeAddresses(response)
{
     var addressNodes = response.getElementsByTagName('address');
     var addresses = new Array(addressNodes.length);

     for (var i = 0; i < addressNodes.length; i++)
     {
         var address = new Address();
         var addressNode = addressNodes.item(i);
         var node = addressNode.firstChild;

         while (node)
         {
             if (node.nodeType == ELEMENT_NODE && node.firstChild != null)
             {
                 address[node.nodeName] = node.firstChild.data;
             }
             node = node.nextSibling;
         }

         addresses[i] = address;
     }

     return addresses;
}

function lookupAddress()
{
    var postcode = document.getElementById("postcode-lookup").value;
    
    if (postcode != null)
    {
        postcode = postcode.replace(new RegExp(" ", "gi"), "");
        if (postcode.length == 5 || postcode.length == 6 || postcode.length == 7)
        {
            var url = "http://dev18.otherworks.com/addresses.xml?postcode=" + postcode;
            load(url);
        }
    }
}

function toolPopup()
{

	var w = 520;
	var h = 700;
	var t = 50;
	var l = 50;
	var popup = window.open("about:blank","popup", "height="+h+", width="+w+", top="+t+", left="+l+", status=yes ,toolbar=yes ,menubar=no, location=no, resizable=yes, scrollbars=yes");
	popup.focus();
}

function sitePopup(win)
{
	win.target="sitePopup";
	var w = 490;
	var h = 620;
	var t = 50;
	var l = 50;
	var popup = window.open("about:blank","sitePopup", "height="+h+", width="+w+", top="+t+", left="+l+", status=yes ,toolbar=yes ,menubar=no, location=no, resizable=yes, scrollbars=yes");
}

function switchProductImage(nxtImg)
{
	var tempSrc = document.getElementById("largeProductImage" + nxtImg).src;
	document.getElementById("largeProductImage" + nxtImg).src = document.getElementById("largeProductImage1").src;
	document.getElementById("largeProductImage1").src = tempSrc;

	var tempSrc = document.getElementById("smallProductImage" + nxtImg).src;
	document.getElementById("smallProductImage" + nxtImg).src = document.getElementById("smallProductImage1").src;
	document.getElementById("smallProductImage1").src = tempSrc;

	curImg = nxtImg;
}

function switchProductImageWorking(nxtImg)
{
	document.getElementById("largeProductImage" + curImg).className = "product-image-hide";
	document.getElementById("largeProductImage" + nxtImg).className = "product-image";

	document.getElementById("smallProductImage" + nxtImg).className = "product-image-hide";
	document.getElementById("smallProductImage" + curImg).className = "product-image";

	curImg = nxtImg;
}
 

/* main workhorse for display ticket logic - should mimic ZslTool.initDisplay()
 * relies on a correct setupHash function in the Product-ticket.vm block containing all the 
 * tickets on that page with their properpties that are needed to calculate whether they should be displayed
 * or not
 */


/* main workhorse for display ticket logic - should mimic ZslTool.initDisplay()
 * relies on a correct setupHash function in the Product-ticket.vm block containing all the 
 * tickets on that page with their properpties that are needed to calculate whether they should be displayed
 * or not
 */
function checkGiftTickets(day, month, year)
{
	// reset warning field
	displayWarning("");
	//obtain user date input
	/*
	 * The value of the HashTable contains an Array with the following fields
	 * 0. seasonal true/false
     * 1. donateable true/false
     * 2. type A/C/CONC/U3 (a string)
     * 3. startDate ( a proper JS Date object)
     * 4. endDate ( as above )
	 */
	var hash = setUpHash();
	
	var selectedDate = new Date(year, month, day);
	
	// donateable box
	var donateable = document.getElementById("donatable").checked;
	var skukeys = $H(hash).keys();
	
	var typehash = {};
	
	for(var i = 0; i<skukeys.length; i++ )
	{
		var skukey = skukeys[i];
		var skuarr = hash[skukey];
		// always hide skus shose donatebale state is unlike the user selected donateable state or it is a non seasonal ticket
		if(skuarr[1] != donateable && skuarr[0])
		{
			handleSkuDisplay(skukey, false);
			continue;
		}
		
		// always display non seasonal skus
		if(!skuarr[0])
		{
			handleSkuDisplay(skukey, true);
			continue;
		}
		
		var isBestMatch = isBestDateMatch(skukey, hash, typehash, selectedDate);
		if(isBestMatch)
		{
			handleSkuDisplay(skukey, true);
		}
		else
		{
			handleSkuDisplay(skukey, false);
		}		
	
	}
	copyQuantities(hash);
	fixRowStyle();
}

function checkTickets(day, month, year)
{

	// reset warning field
	displayWarning("");
	//obtain user date input
	/*
	 * The value of the HashTable contains an Array with the following fields
	 * 0. seasonal true/false
     * 1. donateable true/false
     * 2. type A/C/CONC/U3 (a string)
     * 3. startDate ( a proper JS Date object)
     * 4. endDate ( as above )
     * 5. Winter or Summer ticket - type: W/S
     * 6. Venue: LZ (London), WP(Whipsnade)
     * 7. Special Event: true/false
	 */
	
	var hash = setUpHash();
	
	var selectedDate = new Date(year, month, day);
	
	// donateable box
	var donateable = document.getElementById("donatable").checked;
	
	var skukeys = $H(hash).keys();
	
	if(!isInValidDateRange(selectedDate)) // TODO do wee need to do something else here?
	{
		displayWarning("Tickets can only be bought for tomorrow and for a maximum of 6 months in advance.");
		hideAllTickets(skukeys);
		return;
	}
	
	var typehash = {};
	var londonControlFlag = false;
	var whipsnadeControlFlag = false;
	
	for(var i = 0; i<skukeys.length; i++ )
	{
		var skukey = skukeys[i];
		
		var skuarr = hash[skukey];
		console.log(skuarr);
		var specialEvent = skuarr[7];
		if(!londonControlFlag && skuarr[6] == "LZ" && skuarr[5] == "S") { 
			var lskuStartDate = new Date(skuarr[3]);
			var lskuStartDay = lskuStartDate.getDate();
			var lskuStartMonth = lskuStartDate.getMonth() + 1;
			
			var lskuEndDate = new Date(skuarr[4]);
			var lskuEndDay = lskuEndDate.getDate();
			var lskuEndMonth = lskuEndDate.getMonth() + 1;
			londonControlFlag = true;
		}
		
		if(!whipsnadeControlFlag && skuarr[6] == "WP" && skuarr[5] == "S") {
			//console.log("TEST2");
			var wskuStartDate = new Date(skuarr[3]);
			var wskuStartDay = wskuStartDate.getDate();
			var wskuStartMonth = wskuStartDate.getMonth() + 1;
			
			var wskuEndDate = new Date(skuarr[4]);
			var wskuEndDay = wskuEndDate.getDate();
			var wskuEndMonth = wskuEndDate.getMonth() + 1;
			whipsnadeControlFlag = true;
		}

		// always hide skus shose donatebale state is unlike the user selected donateable state or it is a non seasonal ticket
		if(skuarr[1] != donateable && skuarr[0])
		{
			handleSkuDisplay(skukey, false);
			continue;
		}
		
		// always display non seasonal skus
		if(!skuarr[0])
		{
			handleSkuDisplay(skukey, true);
			continue;
		}
		
		var isBestMatch = isBestDateMatch(skukey, hash, typehash, selectedDate);
		if(isBestMatch)
		{
			handleSkuDisplay(skukey, true);
			if(!specialEvent)
			{
				if(skuarr[6] == "LZ") {
				//console.log("month:"+month+" day:"+day+" skuStartMonth:"+lskuStartMonth+" skuEndMonth:"+lskuEndMonth+" skuStartDay:"+lskuStartDay+" skuEndDay:"+lskuEndDay);
					if(month > lskuStartMonth && month < lskuEndMonth) {
						document.getElementById("renderSnippet37").style.display = 'block';
						document.getElementById("renderSnippet25").style.display = 'none';
					}
					else if(month == lskuStartMonth && day >= lskuStartDay) {
						document.getElementById("renderSnippet37").style.display = 'block';
						document.getElementById("renderSnippet25").style.display = 'none';
					}
					else if(month == lskuEndMonth && day <= lskuEndDay) {	
	    				document.getElementById("renderSnippet37").style.display = 'block';
	    				document.getElementById("renderSnippet25").style.display = 'none';
	    			}
	    			else {
	    				document.getElementById("renderSnippet25").style.display = 'block';
	    				document.getElementById("renderSnippet37").style.display = 'none';
	    			}
	    		}
				else if(skuarr[6] == "WP") {
					if(month > wskuStartMonth && month < wskuEndMonth) {
						document.getElementById("renderSnippet24").style.display = 'none';
	    				document.getElementById("renderSnippet36").style.display = 'block';
					}
					else if(month == wskuStartMonth && day >= wskuStartDay) {
						document.getElementById("renderSnippet24").style.display = 'none';
	    				document.getElementById("renderSnippet36").style.display = 'block';
					}
					else if(month == wskuEndMonth && day <= wskuEndDay) {
	    				document.getElementById("renderSnippet24").style.display = 'none';
	    				document.getElementById("renderSnippet36").style.display = 'block';
	    			}
	    			else {
	    				document.getElementById("renderSnippet24").style.display = 'block';
	    				document.getElementById("renderSnippet36").style.display = 'none';
	    			}
	    		}
    		}
		}
		else
		{
			handleSkuDisplay(skukey, false);
		}
	}
	copyQuantities(hash);
	fixRowStyle();
}

function isBestDateMatch(skukey, skuhash, typehash, date)
{
	var thissku = skuhash[skukey];
	var thistype = thissku[2];
	
	if(!isValidForDate(thissku, date))
	{
		return false;
	}
	
	if(typehash[thistype]==undefined)
	{
		// first of its type so consider it best match for now
		typehash[thistype] = thissku;
		return true;
	}
	else
	{
		// get the current best match and compare
		var currentBestMatch = typehash[thistype];
		if(  (date.getTime() - currentBestMatch[3].getTime()) >
					(date.getTime() - thissku[3].getTime())  )  // we just found a better match
		{
			typehash[thistype] = thissku;
			debug(true);
			return true;		
		}
		else // the one we had is still better
		{
			debug(false);
			return false;
		}
	}
}

function isValidForDate(sku, date)
{
	return (sku[3] <= date && sku[4] >= date);
}

function handleSkuDisplay(skukey, on)
{
	//browser sniffer
	var isIE = !window.opera && navigator.userAgent.indexOf("MSIE") != -1;
	
	if(on)
		document.getElementById(skukey).style.display=(isIE)?"block":"table-row";
	else
		document.getElementById(skukey).style.display="none";
}

function isInValidDateRange(date)
{
	var today = roundDateToDay(new Date());
	return (date.getTime() >= rollDate(today, 1).getTime()
			&& date.getTime() <= rollMonth(today, 8).getTime() );
}


function roundDateToDay(date)
{
	return new Date(date.getFullYear(), date.getMonth(), date.getDate());
}

function rollDate(date, advance)
{
	var oneday = 24 * 60 * 60 * 1000;
	return new Date(date.getTime() + (advance * oneday));
}

/*
 * only positive advancements allowed for the time being
 */
function rollMonth(date, advance)
{
	var year = date.getFullYear();
	var month = date.getMonth(); 
	var day  = date.getDate();
	
	var newyear = year;
	var newmonth = month + advance;

	if(newmonth > 11)
	{
		newmonth = ((newmonth + 1) % 12) - 1;
		newyear = ++year;
	}
	
	var newdate = new Date(newyear, newmonth, day);
	if(newdate.getMonth() == newmonth) 
		return newdate;
	else
	{
		// ok we set something like April 31st, and JavaScript corrected this to be May, 1st which
		// might not be what we want, so go back until we have the correct month
		while(true)
		{
			var newdate = new Date(newyear, newmonth, --day);
			if(newdate.getMonth() == newmonth)
				return newdate;		
		}
	}
}

function hideAllTickets(skus)
{
	for(var i=0; i < skus.length; i++)
	{
		handleSkuDisplay(skus[i], false);
	}
}

function displayWarning(warning)
{
	document.getElementById("warning").innerHTML="<p class=\"warning\">" + warning + "</p>";
}

function fixRowStyle()
{
	var prevValue = "even";
	var table = document.getElementById("ticketTable");
	for(var i=0; i<table.rows.length; i++)
	{
		if( table.rows[i].style.display != "none" )
		{
			table.rows[i].className=prevValue;
			prevValue = (prevValue=="odd") ? "even" : "odd";
		}
	}
	var hash = setUpHash();
	
	//clear qty for hidden skus  
	var skus =$H(hash).keys();
	for(var y=0; y<skus.length; y++)
	{
		var info = document.getElementById(skus[y]);
		//get the value of the select field contained within a given row
		var qty = document.getElementById("qty["+info.rowIndex+"]").options[document.getElementById("qty["+info.rowIndex+"]").selectedIndex].value; 

		if(info.style.display==null || info.style.display=="none" || info.style.display=="")
		{ 
			//set appropriate option to selected using the value of qty for non-fixed skus
			document.getElementById("qty["+info.rowIndex+"]").selectedIndex = 0;
		}						
	}
		
}	
	
function productSkuByDate(field)
{
	if(field.name == "Ddate:LOCAL_WEEKDAY")
	{
		wkCalcDateOffset(field);
	}
	else if(field.name == "Ddate:YEAR")
	{
		wkCalcDayOfWeek(field);
	}
	else
	{		
		wkCalcDayOfWeek(field);
	}	
	checkTickets();
}

/*
 * for any sku that is currently displayed try to find a hidden sku with a qty > 0 
 * and set this qty on the visible sku
 */
function copyQuantities(skuhash)
{
	var skus = $H(skuhash).keys();
	
	for(var i=0; i<skus.length; i++)
	{
		var skuelem = document.getElementById(skus[i]);
		if(skuelem.style.display != "none" );
		{
			var qty = findTypeQty(skuhash[skus[i]][2], skuhash);
			if(qty > 0)
				setQty(skuelem, qty);
		}
	}
}

function findTypeQty(type, skuhash)
{
	var qty = 0;
	
	// iterate over all skus finding the corresponding types
	var skus = $H(skuhash).keys();
	for(var i=0; i < skus.length; i++)
	{
		if(skuhash[skus[i]][2] == type)
		{
			qty = getQty(skus[i]);
			if(qty > 0)
				return qty;
		}
	}
	
	return 0;
}

function getQty(sku)
{
	var qtyelemid = "qty[" + document.getElementById(sku).rowIndex + "]";
	var value = document.getElementById(qtyelemid).options[document.getElementById(qtyelemid).selectedIndex].value;
	if(!isNaN(parseInt(value)) && parseInt(value) > 0 )
		return parseInt(value);
	else
		return 0;
}

function setQty(skuelem, qty)
{
	var skuelemIndex = skuelem.rowIndex; //skuelem needs to be a tr element
	document.getElementById("qty["+ skuelemIndex +"]").options[qty].selected=true;
}

function disableOnBadDates(date)
{
	var month = document.getElementById("Ddate:MONTH").options[document.getElementById("Ddate:MONTH").selectedIndex].value;
	
	var selectTags = document.getElementsByTagName("select");
	if(date.getMonth() == (month-1))
	{
		for(i=0; i<selectTags.length; i++)
		{
			if(selectTags[i].id.indexOf("qty") == 0)
			{
				selectTags[i].disabled=null;
			}
		}
		document.getElementById("warning").innerHTML="";
		return (false);
	}
	else
	{
		for(i=0; i<selectTags.length; i++)
		{
			if(selectTags[i].id.indexOf("qty") == 0)
			{
				selectTags[i].disabled="true";
			}
		}
		document.getElementById("warning").innerHTML="<p class=\"warning\">The date you selected is invalid, please choose another date</p>";
		return (true);
	}	
}