// VARIABLES TO HOLD THE DESCRIPTION OF THE USER'S BAND
var NumHorns=0; // This holds the number of horns in the user's band
var HornPlayerNumber; // Counter of the current hhorn player whose instruments are being described
var HornInstruments = new Array(); // Array of description of instruments for all horn players
var GroupCookie; // This holds the session cookie for the user's Group, to submitted to a server-side database

// VARIABLES TO SETUP SEARCH FOR SONGS MATCHING THE USER'S SEARCH CRITERIA
var searchString; // This is the string that will be written in the form field SearchString
var title = 'all titles'; // this holds the user's song title criterion for the search
var artist = 'all artists'; // This holds the user's artist name criterion for the search
var style = 'all styles'; // This holds the user's music style criterion for the search
var group = 'all groups'; // This holds the user's group size criterion for the search
var queryString; // This is the string that will be sent to MySQL
var queryStart = "SELECT * FROM `TopLevel`"; // Constant beginning of the string to query TopLevel
var queryHasConditions = false; // Flag that query has conditiions so an "AND" clause can be added to queryString
var useSortBy = true; // Used to set a sort order if the user selects other than Title

// VARIABLES USED TO HOLD THE DATA RETURNED FROM THE QUERY OF THE MySQL DATABASE Arrangements

var queryResults = new Array; // This holds the query results being returned to Catalog.shtm
var listSize; // This holds the number of arrangements matching the user's search criteria
var numSegs; // This holds the total number of segments of 10 arrangements each matching the criteria

// VARIABLES USED FOR USER'S SHOPPING CART
var orderIDs = new Array(); // This holds the IDs of all arrangements selected by the user for purchase
var OrderIDCookie; // This holds the IDs of arrangements selected for purchase in Catalog.shtm. 
// It is used by BuyArrangements.shtm to fill the cart.

// VARIABLES TO HOLD THE SHOPPING CART DATA FOR THE USER'S ORDER
var OrderDetails = new Array(); // This array holds all pertinent order information in the cart {ID, TITLE, GROUP, SPECIAL REQUIREMENTS, COST]
var OrderOtherInfo = new Array();  // This array holds all other info from BuyArrangements.shtm [Delivery Options, Adaptations, Total]

// <<<<<<<<< GENERAL FUNCTIONS USED BY THE ArrangementsForSale GROUP >>>>>>>>>

function setFormFocus(F, E) // Reusable function to set the initial focus when opening the web page
{
	document.forms(F.name).elements(E.name).focus();
	document.forms(F.name).elements(E.name).select();
}
// END FUNCTION SetFormFocus

// <<<<<<<<< CLASS OF FUNCTIONS USED IN THE WEB PAGE 'GroupDetails.shtm' >>>>>>>>>
function ResetInstrumentation(F) // Clear the variables from the form
{
	NumHorns=0;
	HornPlayerNumber=1;
	HornInstruments.length = 0;
	setFormFocus(F.name,'NumberOfHorns');
}
// END FUNCTION ResetInstrumentation

function getHornCount(frm) // get the count of the number of horns to be desrcibed by the user and write this to the form's PlayerNumber field
{
	NumHorns = frm.elements('NumberOfHorns').value;
	if (!frm.elements('PlayerNumber').value) // if not set, this is the first one
	{
		frm.elements('PlayerNumber').value="1";
		HornPlayerNumber=1;
	}
	else  // had to change the number
	{
		frm.elements('PlayerNumber').value = NumHorns;
		HornPlayerNumber = frm.elements('NumberOfHorns"');
	}
	frm.elements('ListOfHorns').rows=NumHorns; // resize the textarea to display each player on a new row in the textarea
}
// END FUNCTION GetHornCount

function resetSearch(frm)
{
	title = 'all titles';
	artist = 'all artists';
	style = 'all styles';
	group = 'all groups';
	searchIsReady = false;
	queryHasConditions = false;
	useSortBy = true;
	document.forms('SetupSearch').elements('SearchForTitle').value = title;
	document.forms('SetupSearch').elements('SearchForArtist').value = artist;
	document.forms('SetupSearch').elements('SearchForStyle').value = style;
	document.forms('SetupSearch').elements('searchString').value = 'Your search will be written here';
	document.forms('SetupSearch').elements('optGroup')[3].checked = true;
	setFormFocus(frm.name,'SearchForTitle');
}
// END FUNCTION resetSearch;

function addPlayer(frm) // Update the form field PlayerNumber. Alert user if he has exceeded NumberOfHorns
{
	if (HornPlayerNumber == NumHorns)
	{
		alert(NumHorns + ' players have already been added. \n' + 'Please add more to the count.');
		setFormFocus(frm.name, 'NumberOfHorns');
		return;
	}
	else
	{
		HornPlayerNumber += 1;
		frm.elements('PlayerNumber').value = HornPlayerNumber;
	}
}
// END FUNCTION addPlayer

function addInstrumentForPlayer(frm) // Add a new instrument (principal or doubles) for a given HornPlayerNumber
{
	if (NumHorns==0) // Cannot add an instrument without setting the number of horns to be described
	{
		alert("Please enter the number of horn players first");
		setFormFocus(frm.name, 'NumberOfHorns');
		return;
	}
	var inst = frm.elements('listInstruments').value; // Get the new instrument from the drop-down list listInstruments
	if(inst=='Other (describe)')
	{
		alert('Please describe this instrument in the \n'+'Notes section below before submitting'); // Alert player if he selects 'Other'
	}
	var currentPlayer = HornInstruments[HornPlayerNumber-1]; // retrieve list of instruments for the current HornPlayerNumber
	if (!currentPlayer)
	{
		currentPlayer = 'Player ' + HornPlayerNumber + ": " + inst;
	}
	else
	{
		currentPlayer += '; ' + inst;
	}
	HornInstruments[HornPlayerNumber-1] = currentPlayer // Write the result back to the array
	var listHorns='';
	for (var i = 0; i < HornInstruments.length; i++) // Create a string listing all players described thus far
	{
		listHorns += HornInstruments[i] + '\n';
	}
	frm.elements('ListOfHorns').value = listHorns; // Display the list back to the page
}
// END FUNCTION addInstrumentForPlayer

// <<<<<<<<<<<<<<<<<<<<<<<<< CLASS OF FUNCTIONS USED FOR THE WEB PAGE Catalog.shtm >>>>>>>>>>>>>>>>>>>>

function writeSearch() // Write the user's search criterion as a string to a textarea, 'searchString'  Update every time user adds a criterion
{
	title = document.forms('SetupSearch').elements('SearchForTitle').value; // Did user specify any title criterion?
	artist = document.forms('SetupSearch').elements('SearchForArtist').value; // Did user specify any artist criterion?
	style =  document.forms('SetupSearch').elements('SearchForStyle').value; // Did user specify any style criterion?
	group = 'All Groups'
	for (var i = 0; i < document.forms('SetupSearch').elements('optGroup').length; i++) { // Did user specify any group criterion?
		if (document.forms('SetupSearch').elements('optGroup')[i].checked) {
			group = document.forms('SetupSearch').elements('optGroup')[i].value;
			break;
		}
	}
	searchString = "Title=" + title + "; Artist=" + artist + "; Style=" + style + "; Group=" + group; // Construct the string
	document.forms('SetupSearch').elements('searchString').value = searchString; // Write it back to the page
	// BUILD THE QUERY STRING
	queryString = queryStart;
	if(title!='all titles') {
		queryString+= " WHERE `Title` LIKE " + addDelimiters(title);
		queryHasConditions = true;
		useSortBy =false;
	}
	if(artist!="all artists") {
		if(queryHasConditions) {
			queryString+= " AND `Artist` LIKE " + addDelimiters(artist);
		}
		else {
			queryString+= " WHERE `Artist` LIKE " + addDelimiters(artist);
			queryHasConditions = true;
		}
	}
	if(style!="all styles") {
		if(queryHasConditions) {
			queryString+= " AND `Style` LIKE " + addDelimiters(style);
		}
		else {
			queryString+= " WHERE `Style` LIKE " + addDelimiters(style);
		}
	}
	if(group!="all groups") {
		if(queryHasConditions)
		{
			queryString+= " AND `Group` = " + addQuotes(group);
		}
		else
		{
			queryString+= " where Group = " + addQuotes(group);
		}
	}
	if(useSortBy)
	{
		queryString+= " order by `Title`";
	}
}
// END FUNCTION writeSearch

function addDelimiters(s)
{
	return '"%' + s + '%"';
}
// END FUNCTION addDelimiters

function addQuotes(s)
{
	return '"' + s + '"';
}
// END FUNCTION addQuotes

function conditionText(s) // USE THIS FUNCTION ONLY WHEN THE QUERY IS TO A TABLE THAT HAS NO INTERNATIONAL CHARACTER SUPPORT
{
	var replaceNow;
	var replaceWith;
// Strip whole words 'El 'La' or 'The' from the string if in the beginning
	if(s.indexOf("El ")==0 || s.indexOf("el ")==0 || s.indexOf("La ")==0 || s.indexOf("la ")==0 || s.indexOf("The ")==0 || s.indexOf('the ')==0) {
		s = s.substr(2);
	}
	if(s.indexOf("The ")==0 || s.indexOf('the ')==0) {
		s = s.substr(3);
	}
// Replace all international alpha characters in s
	for(var i=0; i<s.length; i++) {
		replaceNow=false;
		replaceWith="";
		if(s.charCodeAt(i)==225) {
			replaceWith="a";
			replaceNow=true;
		}
		else if(s.charCodeAt(i)==233) {
			replaceWith="e";
			replaceNow=true;
		}
		else if(s.charCodeAt(i)==237) {
			replaceWith="i";
			replaceNow=true;
		}
		else if(s.charCodeAt(i)==241) {
			replaceWith="n";
			replaceNow=true;
		}
		else if(s.charCodeAt(i)==243) {
			replaceWith="o";
			replaceNow=true;
		}
		else if(s.charCodeAt(i)==250 || s.charCodeAt(i)==252) {
			replaceWith="u";
			replaceNow=true;
		}
		if(replaceNow) {
			if(i==0) {
				s = replaceWith + s.substr(1);
			}
			else if(i==s.length) {
				s = s.substr(0,i) + replaceWith;
			}
			else {
				s = s.substr(0,i) + replaceWith + s.substr(i+1);
			}
		}
	}
// Remove inverted exclamantion and question marks - can do this only one time in each string
	for(var i=0; i<s.length; i++) {
		if(s.charCodeAt(i)==161) {
			if(i==0) {
				s = s.substr(1);
				break;
			}
			else if(i==s.length) {
				s = s.substr(0,i);
				break;
			}
			else {
				s = s.substr(0,i) + " " + s.substr(i+1);
				break;
			}
		}
	}
	for(var i=0; i<s.length; i++) {	
		if(s.charCodeAt(i)==191) {
			if(i==0) {
				s = s.substr(1);
				break;
			}
			else if(i==s.length) {
				s = s.substr(0,i);
				break;
			}
			else {
				s = s.substr(0,i) + " " + s.substr(i+1);
				break;
			}
		}
	}
	return addDelimiters(s);
}
// END FUNCTION ConditionText

function openRpt() // If user simply wants to open a PDF file with a list, find which file matches his criteria and open it.
// NOTE: The PDF files are named using the following: docName = 'rpt' + [type of group] + [sort field] + '.pdf'
{
	var docName = 'PDF_Files/rpt'; // Base of the file name
	switch (group) { // First determine the appropriate group and add to the filename
		case 'all groups':
			docName+='AllRepertoire';
			break;
		case 'big band':
			docName+='BigBandRepertoire';
			break;
		case 'conjunto':
			docName+='ConjuntoRepertoire';
			break;
		case 'combo':
			docName+='ComboRepertoire';
			break;
	}
	if (title!='all titles') { // Next determine if there is a sort category
		docName+='ByTitle.pdf'; // Sort by title
	}
	else if(artist!='all artists') { // Sort by artist
		docName+='ByArtist.pdf';
	}
	else if(style!='all styles') { // Sort by style
		docName+='ByStyle.pdf';
	}
	else { // Default to sorting by title
		docName+='ByTitle.pdf';
	}
	window.open(docName);
	return;
}
// END FUNCTION openPDF

// <<<<<<<<<<<<<<<<< CLASS OF FUNCTIONS THAT CONNECT TO THE SERVER AND RETRIEVE QUERY RESULTS >>>>>>>>>>>>>>>>>>>>>>

// function trim is used to remove whitespace from single words
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); };
// functions Ltrim and Rtrim trim whitespace from the beginning and end of strings, respectively
String.prototype.Ltrim = function() { return this.replace(/^\s+/, ''); };
String.prototype.Rtrim = function() { return this.replace(/\s+$/, ''); };

function submitSearch(sql)
{
	sql = formatSQL(sql);
	if(!sql) {
		return;
	}
	var req = getXMLHTTPRequest();
	var dateObj = new Date();
	var t = dateObj.getTime;
	if(!req) {
		alert("Your browser does not support this search mode.\nOpening a list is available in PDF format.");
		openRpt();
		return;
	}
	else {
		var reqURL = 'phpscripts\ArrangementSearch.php?rand=' + t;
		reqURL += "&" + sql;
		reqURL = encodeURIComponent(reqURL);
		req.open("POST",reqURL,true);
		req.onreadystatechange = getResponse(req);
		req.send(null);
	}
}
// END FUNCTION submitSearch

function formatSQL(sql) // Format the SQL so that MySQL can understand it
{
	if(sql=="Your search will be written here") // no constraint - will return all fields??
	{
		alert('An unrestricted search will open hundreds of titles.\nOpening PDF file instead');
		window.open('PDF_Files/rptAllRepertoireByTitle.pdf');
		return false;
	}
	else
	{	
		var firstConstraint = true; 	// use to determine when to write a 'WHERE'
		var hasConstraint = false; 		// true if a field is constrained
		var fieldName;					// name of the field
		var fieldValue;					// value of the field
		var validTokens;				// Does Artist and Title value field have at least one vaid word tokens for refined searching?
		var fSQL= 'SELECT * FROM TopLevel';
		var constraint;					// holds each constraint clause - allows for logical grouping with parens
		var flds = sql.split(";");  	// split the string 'sql' into separate fields
		for(var i=0; i<flds.length; i++) { 	// loop through the array of fields
			var fld = flds[i].split("=");	// split each field into a fieldName and a fieldValue
			fieldName = fld[0].trim();
			fieldValue = fld[1].Ltrim();
			if(fieldValue.indexOf("all " + fieldName.toLowerCase() + 's')!=-1) {
				hasConstraint = false; // determine whether this field is constrained
			}
			else {
				hasConstraint = true;
			}
			if(hasConstraint) {				// add to fSQLonly if there is a constraint
				if(firstConstraint) {		// initiate a where clause
					firstConstraint = false;
					fSQL= fSQL+ ' WHERE ';
				}
				else {						// only continue the where clause
					fSQL= fSQL+ ' AND ';
				}

				if(fieldName == 'Artist' || fieldName == 'Title') {	// these fields are to be split into tokens on word boundaries
					validTokens= false;								// assume no valid token
					var tokens = fieldValue.split(" ");				// split fieldValue into tokens
					if(tokens.length > 1) {							// multiple words
						constraint = '(';							// null the constraint clause
						validTokens= false;							// assume no valid tokens (words of length > 3)
						
						for(var j=0; j<tokens.length; j++) {		// loop through each word
							if(tokens[j].length > 3) {				// token is valid
								validTokens = true;
								if(j==0) {
									constraint = constraint + fieldName + ' LIKE "%' + tokens[j] + '%"';
								}
								else {
									constraint = constraint + ' OR ' + fieldName + ' LIKE "%' + tokens[j] + '%"';
								}
							}
						}
						if(validTokens) {
							fSQL = fSQL + constraint + ')';
						}
						else {
							fSQL = fSQL + fieldValue + ' = "' + fieldValue.trim() + '"';
						}
					}
					else {											// only one token
						fSQL = fSQL + fieldValue + ' = "' + fieldValue.trim() + '"';
					}
				}
				else {												// these fields are not split
					fSQL = fSQL + fieldName + ' = "' + fieldValue + '"';
				}
			}
		}
	}
	return fSQL;
} // END FUNCTION formatSQL

function getXMLHTTPRequest()
{
	var req = null;
	try {
		req = new XMLHttpRequest();
	}
	catch (err) {
		try {
		req = new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch (err) {
			try {
				req = new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch (err) {
				req = null;
			}
		}
	}
	return req;
}
// END FUNCTION getXMLHTTPRequest

function getResponse(req) // GET THE RESPONSE FROM MySQL AND PHP
{
	if(req.readyState == 4 && req.status == 200) {
		var searchResults = decodeURI(req.responseText);
		parseResults(searchResults);
	}
	else {
		setTimeout(getResponse(req),500);
	}
}
// END FUNCTION getResponse

function parseResults(s) // PARSE THE RESULTS RETURNED FROM THE DATABASE AND PLACE THEM ON THE PAGE
{
//	var toplevelrows = s.split('\');
}
// END FUNCTION parseResults
// <<<<<<<<< CLASS OF FUNCTIONS FOR TRACKING USER'S ORDER >>>>>>>>
