nfl.namespace('nfl.GameCenter');

nfl.GameCenter.Engine	= Class.create({
	initialize:function(gameid, gamestate, options){
		this.options		= (typeof options !== 'undefined')?options:{};
		this.config			= (typeof this.options.config !== 'undefined')?this.options.config:{"epicFail":false,"pollinterval":15,"adinterval":30,"videoadinterval":5,"adevents":[]};
		this.polling		= {'increment':'gtd','interval':15,'pe':false};
		this.data			= {};
		this.gameid			= gameid;
		this.gamestate		= gamestate;
		this.loadgtd		= (typeof this.options.donotloadgtd !== 'undefined')?(! this.options.donotloadgtd):true;
		//this.weather		= (typeof this.options.weather !== 'undefined')?this.options.weather:{};
		this.boundHandlers	= {};
		this.pollincprefix	= ''; // for testing purposes only
		this.onFirstErrorShowData = false;
		
		document.observe('gamecenter:data:updating',this.onUpdating.bind(this));
		document.observe('gamecenter:data:updated',this.onUpdate.bind(this));
		document.observe('gamecenter:data:eog',this.onEndOfGame.bind(this));
		document.observe('gamecenter:engine:start',this.start.bind(this));
		document.observe('gamecenter:engine:stop',this.stop.bind(this));
		document.observe('gamecenter:engine:publish',this.publish.bind(this));
		
		if(gamestate == "ACTIVE"){
			this.onFirstErrorShowData = true; 
			/* 
			 * we set this to true so that 
			 * if we encounter a server error on the first xhr attempt 
			 * we publish what we have anyways. 
			*/
			this.start();
		}
		if(gamestate == "POST"){
			/* just grab the gtd but don't poll */
			if(this.loadgtd){this.get();}
		}
		if(gamestate == "PRE"){
			this.data[this.gameid]	= {};
			if(typeof this.options.skeletondata !== 'undefined'){ this.data	= this.options.skeletondata;}
			this.data[this.gameid]	= this.extend(this.data[this.gameid]);
			
			/* publish out */
			this.publish();
		}
		/* every five minutes poll for config object */
		this.cfgpe	= new PeriodicalExecuter(this.getConfig.bind(this),300);
		/* we put this on a timer to allow initialization of class instances to finish */
		setTimeout(function(){document.fire('gamecenter:engine:created',this);}.bind(this),100);
	},
	start:function(){
		if(this.polling.interval > 0){
			console.log('nfl.gamecenter.engine.start');
			this.get();
			this.polling.pe	= new PeriodicalExecuter(this.get.bind(this),this.polling.interval);
			document.fire('gamecenter:engine:started');
		}else{
			console.warn('nfl.gamecenter.engine.start: this.polling.interval = '+this.polling.interval);
		}
	},
	stop:function(){
		if(this.polling.pe){
			console.log('nfl.gamecenter.engine.stop');
			this.polling.pe.stop();
			this.polling.pe	= false;
			document.fire('gamecenter:engine:stopped');
		}else{
			console.warn('nfl.gamecenter.engine.stop: no periodical executer present.');
		}
	},
	restart:function(interval){
		console.log('nfl.gamecenter.engine.restart');
		this.polling.interval = interval;
		this.stop();
		if(this.polling.interval > 0){this.start();}
	},
	get:function(){
		//console.log('nfl.gamecenter.engine.get');
		
		document.fire('gamecenter:data:updating');
		/* request increment file */
		var path	= '/liveupdate/game-center/'+ this.gameid +"/"+this.gameid+"_"+this.pollincprefix+this.polling.increment +'.json?random='+ this.getCacheBustInt();
		var request	= new Ajax.Request(path,{
			method:'get',
			evalScripts:true,
			evalJSON: "force",
			onSuccess:function(XHR){
				var json	= false;
				if(XHR.responseText.strip() == '{}'){
					if(!this.onFirstErrorShowData){
						document.fire('gamecenter:data:updated',{error:true});
						return
					}
					this.data[this.gameid]	= {};
					if(typeof this.options.skeletondata !== 'undefined'){ this.data	= this.options.skeletondata;}
					this.data[this.gameid]	= this.extend(this.data[this.gameid]);
					
					this.publish();
					this.onFirstErrorShowData	= false;
					return
				}
				if(typeof XHR.responseJSON != "undefined"){
					json	= XHR.responseJSON;
				}else{
					json	= eval('(' + XHR.responseText + ')');
				}
				document.fire('gamecenter:data:updated',json);
				this.onFirstErrorShowData	= false;
			}.bind(this),
			onFailure:function(){
				console.warn('nfl.gamecenter.engine.get: failure. onFirstErrorShowData = '+ this.onFirstErrorShowData);
				if(!this.onFirstErrorShowData){
					document.fire('gamecenter:data:updated',{error:true});
					return
				}
				this.data[this.gameid]	= {};
				if(typeof this.options.skeletondata !== 'undefined'){ this.data	= this.options.skeletondata;}
				this.data[this.gameid]	= this.extend(this.data[this.gameid]);
				
				this.publish();
				this.onFirstErrorShowData	= false;
			}.bind(this)
		});
	},
	getState:function(_h){
		var path	= '/liveupdate/game-center/'+ this.gameid +"/"+this.gameid+"_"+this.pollincprefix+this.polling.increment +'.json?random='+ this.getCacheBustInt();
		var request	= new Ajax.Request(path,{
			method:'get',
			evalScripts:true,
			evalJSON: "force",
			onSuccess:_h
		});
	},
	/** getConfig
	 *  updates the config object
	 */
	getConfig:function(){
		var request	= new Ajax.Request("/ajax/gamecenter/config?gameState="+this.gamestate+"&gameId="+this.gameid+"&random="+this.getCacheBustInt(),{
			method:'get',
			evalScripts:true,
			evalJSON: "force",
			onSuccess:function(XHR){
				var json	= false;
				if(typeof XHR.responseJSON != "undefined"){
					json	= XHR.responseJSON;
				}else{
					json	= eval('(' + XHR.responseText + ')');
				}
				var cc = false; var ac = false;
				if(typeof json.config !== 'undefined'){
					if(typeof json.config.epicFail !== 'undefined' && json.config.epicFail !== this.config.epicFail){this.config.epicFail = json.config.epicFail;cc=true; console.log('cc #1');};
					if(typeof json.config.adinterval !== 'undefined' && json.config.adinterval !== this.config.adinterval){this.config.adinterval = json.config.adinterval;ac=true;console.log('cc #2');};
					if(typeof json.config.pollinterval !== 'undefined' && json.config.pollinterval !== this.config.pollinterval){this.config.pollinterval = json.config.pollinterval;cc=true;console.log('cc #3');};
					if(typeof json.config.videoadinterval !== 'undefined' && json.config.videoadinterval !== this.config.videoadinterval){this.config.videoadinterval = json.config.videoadinterval;cc=true;console.log('cc #4');};
					if(typeof json.config.adevents !== 'undefined' && (json.config.adevents.join(',') != this.config.adevents.join(','))){this.config.adevents = json.config.adevents;cc=true;console.log('cc #5 '+Object.toJSON(this.config.adevents)+' != '+ Object.toJSON(json.config.adevents)+' ? '+(json.config.adevents !== this.config.adevents)+' && '+(typeof json.config.adevents !== 'undefined'));}					
					if(typeof json.config.notice !== 'undefined' && json.config.notice !== this.config.notice){this.config.notice = json.config.notice;cc=true; console.log('cc #6');};
				}
				if(this.config.epicFail === true){/* all hell broke loose, ice caps are melting, polar bears are eating people */; window.location.reload();}
				if(cc || ac){
					document.fire('gamecenter:config:updated',this.config);
					if(ac){document.fire('gamecenter:ads:interval:changed',this.config.adinterval);}
				}
				if(typeof this.config.notice !== 'undefined'){
					document.fire('gamecenter:notice:updated',this.config.notice);
				}
			}.bind(this)
		});
	},
	getCacheBustInt:function(){
		var time, d;
		d = new Date();
		d.setSeconds(Math.floor(d.getUTCSeconds() / 10) * 10);
		d.setMilliseconds(0);
		time = d.getTime();
		return time
	},
	/** set
	 *  @param {object} json - json coming in from GSIS
	 * 
	 *  updates internal storage with json updates.
	 */
	set:function(json){
		var dc		= false;
		var gevnts	= [];
		for(var key in json){
			var node	= json[key];
			if(key !== 'nextupdate'){
				/* this is a game object */
				if(typeof this.data[key] === 'undefined'){
					dc				= true;
					this.data[key]	= node;
					this.data[key]	= this.extend(this.data[key]);
					//json = this.data;
					/* this is brand new, advance cursor (skip all the rest of the incremental update logic) */
				}else{
					/* this is not new, figure out what needs to be updated */
					this.clearUpdateFlags(); // first clear any previous 'updated' flags on data
					
					if(typeof node.home !== 'undefined'){
						if(typeof node.home.score !== 'undefined'){this.data[key].home.score = node.home.score;dc=true;}
						if(typeof node.home.abbr !== 'undefined'){this.data[key].home.abbr = node.home.abbr;dc=true;}
						if(typeof node.home.to !== 'undefined'){this.data[key].home.to = node.home.to;dc=true;}
						if(typeof node.home.players !== 'undefined'){
							for(var playerid in node.home.players){
								this.data[key].home.players[playerid] = node.home.players[playerid];dc=true;
							}
						}
						//console.info('starting stat node update process..');
						//console.info('node.home.stats type = '+typeof node.home.stats); 
						if(typeof node.home.stats !== 'undefined'){
							if(typeof this.data[key].home.stats === 'undefined' || this.data[key].home.stats === null){
								//console.info('this.data[key].home.stats = undefined'); 
								this.data[key].home.stats = node.home.stats;
							}else{
								for(stattype in node.home.stats){
									//console.info('updating '+stattype+' stats node. with '+Object.toJSON(node.home.stats[stattype])); 
									if(typeof this.data[key].home.stats[stattype] === 'undefined'){
										//console.log('overwriting all home stats for '+stattype,node.home.stats[stattype]);
										this.data[key].home.stats[stattype] = node.home.stats[stattype];
									}else{
										//console.log('updating players stats for '+stattype+'\n\rPREEXISTING data:'+Object.toJSON(this.data[key].home.stats[stattype]));
										for(var playerid in node.home.stats[stattype]){
											var isUpdated	= !this.statRecordsMatch(this.data[key].home.stats[stattype][playerid],node.home.stats[stattype][playerid]);
											this.data[key].home.stats[stattype][playerid] = node.home.stats[stattype][playerid];dc=true;
											this.data[key].home.stats[stattype][playerid].updated = isUpdated;
										}
										/* re-order stats */
										this.data[key].home.stats[stattype]	= this.getOrderedStatNode(stattype,this.data[key].home.stats[stattype]);
									}
								}
							}
							//console.info('this.data[key].home.stats: ',this.data[key].home.stats);
						}
					}
					
					if(typeof node.away !== 'undefined'){
						if(typeof node.away.score !== 'undefined'){this.data[key].away.score = node.away.score;dc=true;}
						if(typeof node.away.abbr !== 'undefined'){this.data[key].away.abbr = node.away.abbr;dc=true;}
						if(typeof node.away.to !== 'undefined'){this.data[key].away.to = node.away.to;dc=true;}
						if(typeof node.away.players !== 'undefined'){
							for(var playerid in node.away.players){
								this.data[key].away.players[playerid] = node.away.players[playerid];dc=true;
							}
						}
						if(typeof node.away.stats !== 'undefined'){
							if(typeof this.data[key].away.stats === 'undefined' || this.data[key].away.stats === null){
								this.data[key].away.stats = node.away.stats;
							}else{
								for(var stattype in node.away.stats){
									if(typeof this.data[key].away.stats[stattype] === 'undefined'){
										//console.log('overwriting all away stats for '+stattype,node.away.stats[stattype]);
										this.data[key].away.stats[stattype] = node.away.stats[stattype];
									}else{
										//console.log('updating players stats for '+stattype+'\n\rPREEXISTING data:'+Object.toJSON(this.data[key].away.stats[stattype]));
										for(var playerid in node.away.stats[stattype]){
											var isUpdated	= !this.statRecordsMatch(this.data[key].away.stats[stattype][playerid],node.away.stats[stattype][playerid]);
											this.data[key].away.stats[stattype][playerid] = node.away.stats[stattype][playerid];dc=true;
											this.data[key].away.stats[stattype][playerid].updated = isUpdated;
										}
										/* re-order stats */
										this.data[key].away.stats[stattype]	= this.getOrderedStatNode(stattype,this.data[key].away.stats[stattype]);
									}
								}
							}
							//console.info('this.data[key].away.stats: ',this.data[key].away.stats);
						}
					}
					
					if(typeof node.drives !== 'undefined'){
						for(var driveseqid in node.drives){
							if(driveseqid !== 'crntdrv'){
								/* this is a drive sequence */
								if(typeof this.data[key].drives[driveseqid] === 'undefined'){
									this.data[key].drives[driveseqid] = node.drives[driveseqid];dc=true;
								}else{
									if(typeof node.drives[driveseqid].posteam !== 'undefined'){this.data[key].drives[driveseqid].posteam = node.drives[driveseqid].posteam;dc=true;}
									if(typeof node.drives[driveseqid].postime !== 'undefined'){this.data[key].drives[driveseqid].postime = node.drives[driveseqid].postime;dc=true;}
									if(typeof node.drives[driveseqid].phase !== 'undefined'){this.data[key].drives[driveseqid].phase = node.drives[driveseqid].phase;dc=true;}
									if(typeof node.drives[driveseqid].result !== 'undefined'){this.data[key].drives[driveseqid].result = node.drives[driveseqid].result;dc=true;}
									if(typeof node.drives[driveseqid].ydsgained !== 'undefined'){this.data[key].drives[driveseqid].ydsgained = node.drives[driveseqid].ydsgained;dc=true;}
									if(typeof node.drives[driveseqid].penyds !== 'undefined'){this.data[key].drives[driveseqid].penyds = node.drives[driveseqid].penyds;dc=true;}
									if(typeof node.drives[driveseqid].numplays !== 'undefined'){this.data[key].drives[driveseqid].numplays = node.drives[driveseqid].numplays;dc=true;}
									if(typeof node.drives[driveseqid].start !== 'undefined'){this.data[key].drives[driveseqid].start = node.drives[driveseqid].start;dc=true;}
									if(typeof node.drives[driveseqid].end !== 'undefined'){this.data[key].drives[driveseqid].end = node.drives[driveseqid].end;dc=true;}
									if(typeof node.drives[driveseqid].redzone !== 'undefined'){this.data[key].drives[driveseqid].redzone = node.drives[driveseqid].redzone;dc=true;}
									if(typeof node.drives[driveseqid].fds !== 'undefined'){this.data[key].drives[driveseqid].fds = node.drives[driveseqid].fds;dc=true;}
									
									if(typeof node.drives[driveseqid].plays !== 'undefined'){
										for(var playid in node.drives[driveseqid].plays){
											if(typeof this.data[key].drives[driveseqid].plays[playid] === 'undefined'){
												this.data[key].drives[driveseqid].plays[playid] = node.drives[driveseqid].plays[playid];dc=true;
											}else{
												if(typeof node.drives[driveseqid].plays[playid].sp !== 'undefined'){this.data[key].drives[driveseqid].plays[playid].sp = node.drives[driveseqid].plays[playid].sp;dc=true;}
												if(typeof node.drives[driveseqid].plays[playid].qtr !== 'undefined'){this.data[key].drives[driveseqid].plays[playid].qtr = node.drives[driveseqid].plays[playid].qtr;dc=true;}
												if(typeof node.drives[driveseqid].plays[playid].down !== 'undefined'){this.data[key].drives[driveseqid].plays[playid].down = node.drives[driveseqid].plays[playid].down;dc=true;}
												if(typeof node.drives[driveseqid].plays[playid].time !== 'undefined'){this.data[key].drives[driveseqid].plays[playid].time = node.drives[driveseqid].plays[playid].time;dc=true;}
												if(typeof node.drives[driveseqid].plays[playid].yrdln !== 'undefined'){this.data[key].drives[driveseqid].plays[playid].yrdln = node.drives[driveseqid].plays[playid].yrdln;dc=true;}
												if(typeof node.drives[driveseqid].plays[playid].ydstogo !== 'undefined'){this.data[key].drives[driveseqid].plays[playid].ydstogo = node.drives[driveseqid].plays[playid].ydstogo;dc=true;}
												if(typeof node.drives[driveseqid].plays[playid].ydsnet !== 'undefined'){this.data[key].drives[driveseqid].plays[playid].ydsnet = node.drives[driveseqid].plays[playid].ydsnet;dc=true;}
												if(typeof node.drives[driveseqid].plays[playid].posteam !== 'undefined'){this.data[key].drives[driveseqid].plays[playid].posteam = node.drives[driveseqid].plays[playid].posteam;dc=true;}
												if(typeof node.drives[driveseqid].plays[playid].desc !== 'undefined'){
													if(typeof this.data[key].drives[driveseqid].plays[playid].linkified === 'undefined'){
														this.data[key].drives[driveseqid].plays[playid].desc = node.drives[driveseqid].plays[playid].desc;
													}
													dc=true;
												}
												if(typeof node.drives[driveseqid].plays[playid].note !== 'undefined'){this.data[key].drives[driveseqid].plays[playid].note = node.drives[driveseqid].plays[playid].note;dc=true;}
												if(typeof node.drives[driveseqid].plays[playid].players !== 'undefined'){
													if(typeof this.data[key].drives[driveseqid].plays[playid].players === 'undefined'){
														this.data[key].drives[driveseqid].plays[playid].players = node.drives[driveseqid].plays[playid].players;dc=true;
													}else{
														for(var pid in node.drives[driveseqid].plays[playid].players){
															if(typeof this.data[key].drives[driveseqid].plays[playid].players[pid] === 'undefined'){
																this.data[key].drives[driveseqid].plays[playid].players[pid] = node.drives[driveseqid].plays[playid].players[pid];dc=true;
															}else{
																/* exists check other stuff */
															}
														}
													}
												}
											}
										}
									}
								}
							}
						}
						if(node.drives.crntdrv){this.data[key].drives.crntdrv = node.drives.crntdrv;dc=true;}
					}
					if(typeof node.scrsummary !== 'undefined'){
						if(typeof this.data[key].scrsummary === 'undefined' || this.data[key].scrsummary == null){
							this.data[key].scrsummary = node.scrsummary;dc=true;
						}else{
							for(playid in node.scrsummary){
								if(typeof this.data[key].scrsummary[playid] === 'undefined'){
									this.data[key].scrsummary[playid] = node.scrsummary[playid];dc=true;
								}else{
									if(typeof node.scrsummary[playid].qtr !== 'undefined'){this.data[key].scrsummary[playid].qtr = node.scrsummary[playid].qtr;dc=true;};
									if(typeof node.scrsummary[playid].team !== 'undefined'){this.data[key].scrsummary[playid].team = node.scrsummary[playid].team;dc=true;};
									if(typeof node.scrsummary[playid].type !== 'undefined'){this.data[key].scrsummary[playid].type = node.scrsummary[playid].type;dc=true;};
									if(typeof node.scrsummary[playid].desc !== 'undefined'){this.data[key].scrsummary[playid].desc = node.scrsummary[playid].desc;dc=true;};
									if(typeof node.scrsummary[playid].players !== 'undefined'){this.data[key].scrsummary[playid].players = node.scrsummary[playid].players;dc=true;};
								}
							}
						}
					}
					/*
					if(typeof this.options.weather){
						if(typeof this.data[key].weather === 'undefined'){this.data[key].weather = {};}
						if(this.data[key].weather.desc !== this.weather.desc 
							|| this.data[key].weather.temp !== this.weather.temp 
							|| this.data[key].weather.rh !== this.weather.rh 
							|| this.data[key].weather.wind !== this.weather.wind){dc=true;}
						this.data[key].weather = this.weather;
					}
					*/
					if(node.yl){this.data[key].yl = node.yl;dc=true;};
					if(typeof node.qtr !== 'undefined'){
						/* first make sure that this is a change so we don't repeat this */
						if(this.data[key].qtr != node.qtr){
							if((node.qtr).toLowerCase() == '2'){gevnts[gevnts.length] = "endoffirst";}
							if((node.qtr).toLowerCase() == '4'){gevnts[gevnts.length] = "endofthird";}
							if((node.qtr).toLowerCase() == 'halftime' || (node.qtr).toLowerCase() == 'half'){gevnts[gevnts.length] = "halftime";}
							if((node.qtr).toLowerCase() == 'final' || (node.qtr).toLowerCase() == 'final overtime'){gevnts[gevnts.length] = "endofgame"; }
						}
						this.data[key].qtr = node.qtr;
						dc=true;
					};
					if(typeof node.down !== 'undefined'){this.data[key].down = node.down;dc=true;};
					if(typeof node.togo !== 'undefined'){this.data[key].togo = node.togo;dc=true;};
					if(typeof node.redzone !== 'undefined'){this.data[key].redzone = node.redzone;dc=true;};
					if(typeof node.clock !== 'undefined'){this.data[key].clock = node.clock;dc=true;};
					if(typeof node.posteam !== 'undefined'){this.data[key].posteam = node.posteam;dc=true;};
					if(typeof node.note !== 'undefined' && node.note !== null){
						if(this.data[key].note !== node.note && (node.note).toLowerCase() === 'timeout'){ gevnts[gevnts.length] = "timeouts"; }
						this.data[key].note = node.note;dc=true;
					};
					this.data[key]	= this.extend(this.data[key]);
					//this.data[key]	= this.extend(node);
				}
			}
			if(key === 'nextupdate'){this.polling.increment = node;};
		}
		/* do initial onload bia code */
		if(document.cookies.get('gcolbia') == ''){
			gevnts[gevnts.length] = 'onload';
			if(this.config.adevents.indexOf('onload') > -1){
				document.cookies.set('gcolbia','true',document.cookies.getExipiry(0,24,0),'/');
			}
		}
		if(dc){
			if(typeof this.config.adevents !== 'undefined'){
				/* check increment file for ad events */
				var triggerAd	= false;
				for(var i=0; i < gevnts.length;i++){
					if(this.config.adevents.indexOf(gevnts[i]) > -1){
						/* we need to show a break in action ad */
						triggerAd	= true;
						break
					}
				}
			}
			if(this.data[this.gameid].qtr == 'Final' || this.data[this.gameid].qtr == 'final overtime'){document.fire('gamecenter:data:eog'); }
			/* data changed, fire event */
			document.fire('gamecenter:data:changed',{"gtd":this.data,"inc":json,"gameid":this.gameid});
			if(triggerAd){ console.info('trigger ad event sent from engine.'); document.fire('gamecenter:data:adevent',gevnts);}
			//console.log("GC DATA ENGINE: DATA",this.data);
		}
		
	},
	getOrderedStatNode: function(stattype,statnode){
		var thereisordertotheuniverse	= [];
		var statfunc					= false;
		var newstatnode					= null;

		switch(stattype){
			case "defense":
				statfunc	= function(a,b){return (b['tkl']+(b['ast'] * .01))-(a['tkl']+(a['ast'] * .01));};
				break;
			case "passing":
				statfunc	= function(a,b){return (b['yds'])-(a['yds']);};
				break
			case "rushing":
				statfunc	= function(a,b){return (b['yds'])-(a['yds']);};
				break;
			case "receiving":
				statfunc	= function(a,b){return (b['yds'])-(a['yds']);};
		}
		
		if(statfunc !== false){
			var hasnodes	= false;
			for(pid in statnode){
				hasnodes	= true; statnode[pid].id = pid;
				thereisordertotheuniverse[thereisordertotheuniverse.length] = statnode[pid];
			}
			if(hasnodes){
				thereisordertotheuniverse.sort(statfunc);
				//console.log('thereisordertotheuniverse = '+ thereisordertotheuniverse.toJSON());	
				thereisordertotheuniverse.each(function(__pstat){
					if(newstatnode === null){ newstatnode = {};}
					newstatnode[__pstat.id]	= __pstat;
				});
			}
		}
		return (newstatnode === null)?statnode:newstatnode;
	},
	statRecordsMatch: function(pstat1,pstat2){
		var s1	= Object.toJSON(pstat1);
		var s2	= Object.toJSON(pstat2);
		if(typeof s1 === 'undefined' || typeof s2 === 'undefined'){ return false; } //return false for now, change this
		if(s1.length > s2.length){
			s2	= s2.substring(0,s2.indexOf('}'));
			if(s1.startsWith(s2)){ return true }
		}
		if(s2.length > s1.length){
			s1	= s1.substring(0,s1.indexOf('}'));
			if(s2.startsWith(s1)){ return true }
		}
		if(s1.length == s2.length){ if(s1 == s2){ return true }}
		return false
	},
	clearUpdateFlags: function(){
		if(typeof this.data[this.gameid] !== 'undefined'){
			if(typeof this.data[this.gameid].home !== 'undefined'){
				if(typeof this.data[this.gameid].home.stats !== 'undefined'){
					for(skey in this.data[this.gameid].home.stats){
						for(pkey in this.data[this.gameid].home.stats[skey]){
							this.data[this.gameid].home.stats[skey][pkey].updated = false;
						}
					}
				}
			}
			if(typeof this.data[this.gameid].away !== 'undefined'){
				if(typeof this.data[this.gameid].away.stats !== 'undefined'){
					for(skey in this.data[this.gameid].away.stats){
						for(pkey in this.data[this.gameid].away.stats[skey]){
							this.data[this.gameid].away.stats[skey][pkey].updated = false;
						}
					}
				}
			}
		}
	},
	extend:function(gamenode){
		//console.log('engine.extend: extending:\n\r'+Object.toJSON(gamenode)+'\n\rwith:\n\r'+Object.toJSON(this.options));
		/* for players we only want to extend if there is no existing data*/
		if(typeof this.options.players !== 'undefined'){
			if(this.options.players.home){
				//console.info('extending '+ Object.toJSON(gamenode.home) +' with players');
				if(typeof gamenode.home === 'undefined'){gamenode.home = {};}
				if(typeof gamenode.home.players === 'undefined' || gamenode.home.players === null){ gamenode.home.players	= this.options.players.home.players;}
			}
			if(this.options.players.away){
				//console.info('extending '+ Object.toJSON(gamenode.away) +' with players');
				if(typeof gamenode.away === 'undefined'){gamenode.away = {};}
				if(typeof gamenode.away.players === 'undefined' || gamenode.away.players === null){ gamenode.away.players	= this.options.players.away.players;}
			}
		}
		/* check for teams */
		if(typeof this.options.teams !== 'undefined'){
			for(key in this.options.teams.home){
				gamenode.home[key]	= this.options.teams.home[key];/* add to home team node */
			}
			for(key in this.options.teams.away){
				gamenode.away[key]	= this.options.teams.away[key];/* add to away team node */
			}
		}
		/* for weather and media we don't care if there is existing data or not */
		if(typeof this.options.weather !== 'undefined'){
			gamenode.weather	= this.options.weather;
		}
		if(typeof this.options.media !== 'undefined'){
			gamenode.media = this.options.media;
		}
		if(typeof this.options.stadium !== 'undefined'){
			gamenode.stadium = this.options.stadium;
		}
		return gamenode
	},
	publish: function(){
		document.fire('gamecenter:data:changed',{"gtd":this.data,"inc":this.data});
	},
	onUpdating: function(event){
		
	},
	onUpdate: function(event){
		var json	= event.memo;
		//console.log('nfl.gamecenter.engine.onUpdate');
		/* update occured */
		if(this.config.epicfail){
			/* all hell broke loose, ice caps are melting, polar bears are eating people */
			//window.location.reload();
		}
		if(!json.error && !json.empty){
			this.set(json);
		}else{
			console.warn('nfl.gamecenter.engine.onUpdate: NO DATA!');
		}
	},
	onEndOfGame: function(event){
		this.gamestate = "POST";
		/* stop polling */
		this.stop();
		console.info('EOG: shutting down GC engine.');
		/* reload page */
		//window.location.reload();
	}
});