//This script deals with the inrunning
//initialize() is called first, this then calls load_match_file()
//load_match_file() then calls parse_match_file()
//parse_match_files() calls load_situation_file()


//create global GameManager
processMochiTAL = function (dom, data) {
	//The nodeType property returns the type of node, 1 being 'element'
	if (dom.nodeType != 1) {
		return;
	}
	
	var attr;
	
	// handle repeat tags (tablebottom)
	attr = getAttribute(dom, "mochi:repeat");
	
	if (attr) {
		//remove the repeat attribute - we're processing now so will be done with it
		dom.removeAttribute("mochi:repeat");
		var parent = dom.parentNode;
		attr = attr.split(" ");
		var name = attr[0];
		var lst = valueForKeyPath(data, attr[1]);
		
		if (!lst) {	
			return;
		}
		
		for (var i=0; i<lst.length; ++i) {
			data[name] = lst[i];
			var newDOM = dom.cloneNode(true);
			processMochiTAL(newDOM, data);
			parent.insertBefore(newDOM, dom);
		}
		
		parent.removeChild(dom);
		return;
	}
	
	// handle content tags
	attr = getAttribute(dom, "mochi:content");
	if (attr) {
		dom.removeAttribute("mochi:content");
		replaceChildNodes(dom, valueForKeyPath(data, attr));
		return;
	}
	
	//handle formatted content tags
	attr = getAttribute(dom, "mochi:formattedContent");
	if (attr) {
		dom.removeAttribute("mochi:formattedContent");
		replaceChildNodes(dom, 	numberFormatter("#.#%")(valueForKeyPath(data, attr)));
		return;
	}
	
	// handle custom link...
	attr = getAttribute(dom, "mochi:customLink");
	if (attr) {
		dom.removeAttribute("mochi:customLink");
		attr = attr.split(" ");
		var href = attr[0];
		var ref1 = attr[1];
		var ref2 = attr[2];
		
		dom.href = href + "?" + ref1 + "=" + valueForKeyPath(data, "item.match");
	}
	
	// make a shallow copy of the child nodes - in case it changes due to repeat attr
	var nodes = list(dom.childNodes);
	
	// now iterate through them and continue the processing
	for (var i=0; i<nodes.length; ++i) {
		processMochiTAL(nodes[i], data);
	}	
};

getAttribute = function (dom, key) {
	try {
		return dom.getAttribute(key);
	} catch (e) {
		return null;
	}
};

valueForKeyPath = function (data, keyPath) {
	var chunks = keyPath.split(".");
	while (chunks.length && data) {
		data = data[chunks.shift()];
	}
	return data;
};

GameManager = function() {
	this.templates = [];
	
	//This denotes the amount of time that's passed since we opened the pag
	this.numTicks = 0;
	
	//Set up the various paths for the files we need to access
	this.csvFilePath = "/football_sites/football_dectech/scripts/inrunning_data/";
	this.predictionScriptName = "/cgi-bin/new_site/inrunning/GetPrediction.pl";
	this.situationFilePath = "/football_sites/football_dectech/loadSituationFile.php?url=";

//	this.csvFilePath = "/football_dectech/scripts/inrunning_data/";
//	this.predictionScriptName = "/cgi-bin/new_site/inrunning/GetPrediction.pl";
//	this.situationFilePath = "/football_dectech/loadSituationFile.php?url=";
	
	this.data = null;
	
	this.situationFileList = new Array();
	
	this.deferredSituationList = new Array();
	this.deferredPredictionList = new Array();
	
	//Variables that let us determine whether we're ready to go to the next phase in the script
	this.numSituationLoading = 0;
	this.numPredictionLoading = 0;
	
	this.globalIntervalID = null;
	
	bindMethods(this);
};
GameManager.prototype = {
	// initialization
	"initialize": function () {
		log("initialising...");
		
		//load in the file containing info about matches (populated by crontab)
		this.load_match_file(this.csvFilePath + "match_file.xml?x=x");
		
		//Grab the table from the .php file - we'll be adding rows of data to this later 
		var templates = getElementsByTagAndClassName(null, "mochi-template");
		
		for (var i=0; i<templates.length; ++i) {
			var template = templates[i];
			
			var proto = template.cloneNode(true);
			removeElementClass(proto, "mochi-template");
			this.templates.push({"template": proto, "node": template});
		}
		
		//Set up the arrays we're going to use to hold the data		
		this.data = new Object();
		this.data.games = new Array();
		this.data.tempData = new Array();
	}, 
	
	"load_match_file": function (match_file_url) {
		log("loading match file... " + match_file_url);
		if (this.deferred) {
			this.deferred.cancel();
		}
		
		var d = doXHR(match_file_url, {
						mimeType: 'text/xml',
						headers: {Accept: 'text/xml'}
						});
						
		//Once we're done loading, call parse_match_file	
		d.addCallback(this.parse_match_file);
						
		d.addBoth(function (res) {
			self.deferred = null;
			return res;
		});
		
		d.addErrback(function (err) {
			if (err instanceof CancelledError) {
				return;
			}
			if (err instanceof XMLHttpRequestError) {
				log("***match file doesn't exist! " + match_file_url);
				this.hideTable();
				document.getElementById('status').innerHTML="There is a problem with this page - try again later. If the problem persists, <a href='mailto:predictor@dectech.org'>contact us</a>.";
			}
		});
	},
	
	"parse_match_file": function (req) {
		log("parsing match file...");
		
		//Get the XML document into a variable
		var xml = req.responseXML;
		
		//Get the parent element
		xmlRoot = xml.firstChild;
						
		//Get past the comments in the XML file
		while (xmlRoot.nodeType!=1) {
			xmlRoot=xmlRoot.nextSibling;
		}
		
		//get all the tags named 'competition'
		var competitionList = xmlRoot.getElementsByTagName("Competition");
		
		log("length of competition list: " + competitionList.length)
		
		for (k=0; k<competitionList.length; ++k) {		
			//get all elements names 'match'
			var matchList = competitionList[k].getElementsByTagName("Match");
			var match = null;
			var matchDate = null;

			log("length of match list: " + matchList.length)

			if(matchList.length > 0) {
				//get the leagueID to construct the filename
				for (i=0; i<matchList.length; ++i) {
					//get the current match
					match = matchList[i];
			
					//grab the ID of the match	
					uID = getNodeAttribute(match, "uID");
							
					//grab home and awway team ID (opta style ID) - need these later to get the prediction data
					homeID = getNodeAttribute(match, "opta_home_team_id");
					awayID = getNodeAttribute(match, "opta_away_team_id");
			
					//convert opta home and away IDs to Dectech IDs and names
					homeDectechID = getNodeAttribute(match, "dectech_home_team_id");
					awayDectechID = getNodeAttribute(match, "dectech_away_team_id");
					homeSoccerbaseID = getNodeAttribute(match, "soccerbase_home_team_id");
					awaySoccerbaseID = getNodeAttribute(match, "soccerbase_away_team_id");
					homeTeamName = getNodeAttribute(match, "home_team_name");
					awayTeamName = getNodeAttribute(match, "away_team_name");
					
					//get match date details
					matchDate = getNodeAttribute(match, "date");
					matchDateList=matchDate.split(" ");
					matchTimeList=matchDateList[1].split(":");	
					matchDateList=matchDateList[0].split("-");
			
					//this is the Opta file we need to access the match data
					currFile = "position-8-"+uID+".xml";

					//add an element for each match to the various lists as required...
					this.deferredSituationList[currFile] = null;
					this.deferredPredictionList[currFile] = null;
					this.situationFileList[i] = currFile;
					this.data.tempData[currFile] = new Object();
			
					//get the date of the match and format correctly
					matchDateObject = new Date(matchDateList[0], Number(matchDateList[1])-1, Number(matchDateList[2]), matchTimeList[0], matchTimeList[1], matchTimeList[2]);
					matchDay = matchDateObject.getDate();
					if(matchDay<10)
						matchDay = "0"+matchDay;
					matchMonth = (matchDateObject.getMonth()+1);
					if(matchMonth<10)
						matchMonth = "0"+matchMonth;
			
					//initialise the tempData associative array - use temporary numbers for some of the fields
					this.data.tempData[currFile].dectechHome = homeDectechID;
					this.data.tempData[currFile].dectechAway = awayDectechID;
					this.data.tempData[currFile].soccerbaseHome = homeSoccerbaseID;
					this.data.tempData[currFile].soccerbaseAway = awaySoccerbaseID;
					this.data.tempData[currFile].optaHome = homeID;
					this.data.tempData[currFile].optaAway = awayID;
					this.data.tempData[currFile].homeTeamName = homeTeamName;
					this.data.tempData[currFile].awayTeamName = awayTeamName;
					this.data.tempData[currFile].match = uID;
					this.data.tempData[currFile].score = "0-0";
					this.data.tempData[currFile].homeScore = "0";
					this.data.tempData[currFile].awayScore = "0";
					this.data.tempData[currFile].minute = "0";
					this.data.tempData[currFile].matchDate = matchDay + "/" + matchMonth + "/" + matchDateObject.getFullYear();
				}
			} else {
				this.hideTable();
				document.getElementById('status').innerHTML="There are no matches in this conference at present - please check back when there are upcoming matches.";
			}
		}
		if(matchList.length > 0) {
			this.load_situation_files();
		}
	},

	"load_situation_files": function () {
		// load game_situation_file - the file created by Opta containing the match data
		for(var fileName in this.deferredSituationList) {
			log("loading situation file: "+this.situationFilePath+fileName+"&amp;tick="+this.numTicks+"&amp;minute="+this.data.tempData[fileName].minute);
			
			//constructs the full path and request vars for the PHP file which creates the situation file we need
			var situationFile = this.situationFilePath+fileName+"&amp;tick="+this.numTicks+"&amp;minute="+this.data.tempData[fileName].minute;
			
			//increase the counter variable to show that we're loading the next file (this is decreased when loading is finished)
			++this.numSituationLoading;
			
			var d = doXHR(situationFile, {
							mimeType: 'text/xml',
							headers: {Accept: 'text/xml'}
							});
			
			//create array of situation file objects
			this.deferredSituationList[fileName] = d;
			
			//when finished loading, call parse_situation_file()
			d.addCallback(this.parse_situation_file);
			
			d.addBoth(function (res) {
				//self.deferredList[fileName] = null;
				
				//self.deferred = null;
				return res;
			});
			d.addErrback(function (err) {
				log("ERROR: " + err);

				if (err instanceof CancelledError) {
					log("cancelled");
					return;
				}
				if (err instanceof XMLHttpRequestError) {
					log("***situation file doesn't exist! " + situationFile);
					--gameManager.numSituationLoading;
				
					if(gameManager.numSituationLoading==0) {
						log("finished loading");
						gameManager.load_prediction_files();
					}
				}
			});			
		}
	},

	"parse_situation_file": function (req) {
		//Parse situation file (file created by Opta containing the match data)
		log("parsing situation file...");
		log("***" + req + "-" + typeof(req));
		
		//decrease counter variable - when at zero we can proceed to load_prediction_file()
		--this.numSituationLoading;
							
		if(window.ActiveXObject){ // If IE Windows
			log("IE");
			var xml = new ActiveXObject("Msxml2.DOMDocument.6.0");
			log("zzz" + req.responseText + "zzz");
			xml.async = false;
			xml.loadXML(req.responseText);
			log("Got XML");				
		} else {
			log("Not IE");
			var xml = req.responseXML;
			log("Got XML");
		}		
		
		log("Before XML stuff");
		//log("XML:", (new XMLSerializer()).serializeToString(xml));
		log("xxx " + xml + " xxx");
		
		xmlRoot = xml.firstChild;
		log ("loop problems!")
		log("XXX" + xmlRoot + "XXX");
		log("YYY" + xmlRoot.nodeType + "YYY");
		log("XXXX");
		
		while (xmlRoot.nodeType!=1) {
			xmlRoot=xmlRoot.nextSibling;
		}
		
		log("Got XML Root");
		
		//Get match ID
		var uID = getNodeAttribute(xmlRoot, "id");
		
		log("***uID " + uID);
						
		if(uID!=null) {
			//get league ID
			//var leagueID = getNodeAttribute(xmlRoot, "competition_id");
			var leagueID = 8;
			
			//construct name of Opta file we are accessing (for associative arrays)
			var currFile = "position-"+leagueID+"-"+uID+".xml";
			
			log("*********" + currFile);
			log(this.data.tempData);
			
			//get the start times of period 1 and period 2 (the two halves)
			//if period_2_start is undefined, the second half hasn't started yet
			var period_1_start = getNodeAttribute(xmlRoot, "period_1_start");
			var period_2_start = getNodeAttribute(xmlRoot, "period_2_start");
			
			log("period_1_start: " + period_1_start);
			log("period_2_start: " + period_2_start);
			
			//get all XML elements named 'event' - these are all the passes, goals etc
			var eventList = xmlRoot.getElementsByTagName("Event");
			var ev = null;
			
			//initialise the score
			var homeScore = 0;
			var awayScore = 0;
			
			//initialise the time for this match
			var currTime = 0;
			
			//if this match hadn't previously started, give it a start time of zero
			if(this.data.tempData[currFile].minute==undefined) 
				this.data.tempData[currFile].minute = "0";
			
			for (i=0; i<eventList.length; ++i) {
				//set tmpTime to the time in the current event
				var tmpTime = getNodeAttribute(ev, "period_minute");
				
				//if the time of the current event is greater that the previous one, set currTime as tmpTime
				if (tmpTime > this.data.tempData[currFile].minute)
					currTime = tmpTime;
			
				ev = eventList[i];
				
				//get the team that has created this event
				var teamID = getNodeAttribute(ev, "team_id");
				
				//get the home team ID
				var currHome = this.data.tempData[currFile].optaHome;
				
				//get the vent type
				var eventType = getNodeAttribute(ev, "event_type_id");
								
				switch(eventType) {
					case "16":
						//if the event is a goal
						if (teamID == currHome) {
							++homeScore;
						} else {
							++awayScore;
						}
						break;
					case "26":
						//if the event is an own goal
						if (teamID == currHome) {
							++awayScore;
						} else {
							++homeScore;
						}
						break;
				}
			}
			
			//get period ID - 1 is first half, 2 is second
			var period_id = getNodeAttribute(ev, "period_id");
			
			//set the scores for the match we're on
			this.data.tempData[currFile].homeScore = homeScore;
			this.data.tempData[currFile].awayScore = awayScore;
			this.data.tempData[currFile].score = homeScore + "-" + awayScore;
			
			log("getting current match time for " + currFile);
			//get the time of the match we're on
			this.getCurrentMatchTime(period_1_start, period_2_start, currFile);
		}
		if(this.numSituationLoading==0) {
			log("finished loading");
			this.load_prediction_files();
		}
	},
	
	// load prediction_file
	"load_prediction_files": function () {
		log("loading prediction files...");
		for(var i = 0; i < this.situationFileList.length; ++i) {
			fileName = this.situationFileList[i];
			
			++gameManager.numPredictionLoading;
						
			var awayID = this.data.tempData[fileName].soccerbaseAway;
			var homeID = this.data.tempData[fileName].soccerbaseHome;
			var minute = this.data.tempData[fileName].minute;
			var homeGoals = this.data.tempData[fileName].homeScore;
			var awayGoals = this.data.tempData[fileName].awayScore;
			var date = this.data.tempData[fileName].matchDate;
			date = date.replace(new RegExp(/\//g),'');
									
			this.getPrediction(this.predictionScriptName, {homeID: homeID, awayID: awayID, homeGoal: homeGoals, awayGoal: awayGoals, minute: minute, fileName: fileName, date: date});
		}
	}, 
	
	"getPrediction": function(url, vars) {
		log("getting prediction...", url, vars.fileName, vars.homeID, vars.awayID, vars.homeGoal, vars.awayGoal, vars.minute, vars.date);
		var d;
		if (this.deferred) {
			this.deferred.cancel();
		}
				
		d = loadJSONDoc(url, vars);
				
		gameManager.deferredPredictionList[vars.fileName] = d;
		var self = this;
			
		d.addBoth(function (res) {
			self.deferred = null;
			return res;
		});
				
		d.addCallback(this.setPrediction);
		d.addErrback(function(err) {
			if (err instanceof CancelledError) {
				return;
			}
			log("problem getting prediction: " + err);
			--gameManager.numPredictionLoading;
						
			if(gameManager.numPredictionLoading == 0) {
				gameManager.displayCurrentData();
			}
		});
		return d;
	},
	
	"setPrediction": function(data) {
		log("setting prediction...", data);
		// store data for later
		this.data.tempData[data.fileName].homeWin = data.homeWin;
		this.data.tempData[data.fileName].awayWin = data.awayWin;
		this.data.tempData[data.fileName].draw = data.draw;
								
		--gameManager.numPredictionLoading;
		
		if(gameManager.numPredictionLoading == 0) {
			this.displayCurrentData();
		}
	},
	
	"getCurrentMatchTime": function(period_1_start, period_2_start, curr_file) {
		log("getting current match time... " + period_1_start + " - " + period_2_start + " - " + curr_file);
		
		if(period_1_start==null) {
			this.data.tempData[curr_file].minute = 0;
		} else {
			curDateString = getCurrentDate();
			var curTemp = curDateString.split(" ");
			var curTempDate = curTemp[0].split("-");
			var curTempTime = curTemp[1].split(":");
			var curYear = curTempDate[0];
			var curMonth = curTempDate[1];
			var curDay = curTempDate[2];
			var curHour = curTempTime[0];
			var curMinute = curTempTime[1];
			var curSecond = curTempTime[2];
			curDate = new Date();
			curDate.setFullYear(curYear);
			curDate.setMonth(curMonth - 1);
			curDate.setDate(curDay);
			curDate.setHours(curHour);
			curDate.setMinutes(curMinute);
			curDate.setSeconds(curSecond);
			var period1Temp = period_1_start.split(" ");
			var period1TempDate = period1Temp[0].split("-");
			var period1TempTime = period1Temp[1].split(":");
			var period1Year = period1TempDate[0];
			var period1Month = period1TempDate[1];
			var period1Day = period1TempDate[2];
			var period1Hour = period1TempTime[0];
			var period1Minute = period1TempTime[1];
			var period1Second = period1TempTime[2];
			period1Date = new Date();
			period1Date.setFullYear(period1Year);
			period1Date.setMonth(period1Month - 1);
			period1Date.setDate(period1Day);
			period1Date.setHours(period1Hour);
			period1Date.setMinutes(period1Minute);
			period1Date.setSeconds(period1Second);
			var diffMilli = (curDate.getTime()+(this.numTicks*60000)) - period1Date.getTime();
			this.data.tempData[curr_file].minute = Math.round(diffMilli / 60000);
			if(this.data.tempData[curr_file].minute < 0) {
				this.data.tempData[curr_file].minute = 0;
			} else if(this.data.tempData[curr_file].minute >= 45) {
				if(period_2_start==null) {
					this.data.tempData[curr_file].minute = 45;
				} else {
					var period2Temp = period_2_start.split(" ");
					var period2TempDate = period2Temp[0].split("-");
					var period2TempTime = period2Temp[1].split(":");
					var period2Year = period2TempDate[0];
					var period2Month = period2TempDate[1];
					var period2Day = period2TempDate[2];
					var period2Hour = period2TempTime[0];
					var period2Minute = period2TempTime[1];
					var period2Second = period2TempTime[2];
					period2Date = new Date();
					period2Date.setFullYear(period2Year);
					period2Date.setMonth(period2Month - 1);
					period2Date.setDate(period2Day);
					period2Date.setHours(period2Hour);
					period2Date.setMinutes(period2Minute);
					period2Date.setSeconds(period2Second);
					var diffMilli = (curDate.getTime()+(this.numTicks*60000)) - period2Date.getTime();
					if(diffMilli > 0) {
						this.data.tempData[curr_file].minute = Math.round(diffMilli / 60000) + 45;
						if(this.data.tempData[curr_file].minute > 90) {
							this.data.tempData[curr_file].minute = 90;
						}
					} else {
						this.data.tempData[curr_file].minute = 45;
					}
				}
			}
		}
	},
			
	"displayCurrentData": function() {
		log("displaying current data...");
				
		for(var i=0; i<this.situationFileList.length; ++i) {
			fileName = this.situationFileList[i];
						
			if(this.data.tempData[fileName].minute==undefined) 
				this.data.tempData[fileName].minute = "0";
			if(this.data.tempData[fileName].draw==undefined) 
				this.data.tempData[fileName].draw = 0;
			if(this.data.tempData[fileName].awayWin==undefined) 
				this.data.tempData[fileName].awayWin = 0;
			if(this.data.tempData[fileName].homeWin==undefined) 
				this.data.tempData[fileName].homeWin = 0;
		}
		
		this.data.games = new Array();
		var i=0;
		for(game in this.data.tempData) {
			this.data.games[i++] = this.data.tempData[game];
		}
		var sortkey = "gameDate";
		var sortstyle = "str";
		
		var sortfunc = SortTransforms[sortstyle];
		if (!sortfunc) {
			throw new TypeError("unsupported sort style" + repr(sortstyle));
		}
		
		var games = this.data.games;
		for (var i=0; i<games.length; ++i) {
			var game = games[i];
			if (this.sortStyle=="isoDate")
				game.__sort__ = sortfunc(convertEnglishAndAmerican(game[sortkey]));
			else
				game.__sort__ = sortfunc(game[sortkey]);
			
		}
		
		//Populate the rows in the table (add rows to our template variable)
		for (var i=0; i<this.templates.length; ++i) {
			var template = this.templates[i];
			//Copy the current node
			var dom = template.template.cloneNode(true);
			//Process the current node
			processMochiTAL(dom, this.data);
			//Swap with the previously empty node
			template.node = swapDOM(template.node, dom);
		}
	},
		
	"handleStartMatch": function () {
		log("handling start of match...");
		interval= 60000;
		if(this.globalIntervalID!=null)
			clearTimeout(this.globalIntervalID);
		this.globalIntervalID = setInterval(this.nextTick, interval);
	},
	
	"nextTick": function () {
		//Move on to the next tick, then reload the situation files using the new time
		log("next tick");
		++this.numTicks;
		this.load_situation_files();
	},
	
	"hideTable": function() {
		tableTopElement = document.getElementById('tabletop');
		setStyle(tableTopElement, {'display': 'none'});
		tableElement = document.getElementById('tableall');
		setStyle(tableElement, {'display': 'none'});
	}
};

SortTransforms = {
	"str": operator.identity,
	"isoDate": isoDate
};

gameManager = new GameManager();
addLoadEvent(gameManager.initialize);
addLoadEvent(gameManager.handleStartMatch);
