/* This would be the pets brain and reflexes
  ------------------------------------------
  1. has a hieraticle structure telling it how to go from any animation to any other animation, by going
  back and forth between the sitting position.
  
  2. stores jobs in a linear order to be processed one at a time
  
  3. retrieves jobs in a linear order and processes them
  
  4. fires events what may errase all jobs or append jobs to the job que
 */
 
function Brain(petobj,xmlobj){
	var me = this;
	var jobList = new Array, jobCount =0, currentJob=0;
	var passport = petobj.passport;
	// var mood = pet.mood;
	var task 			= "sit";
	var taskframe 		= 1;
	var taskframes 		= 1;
	var taskdirection	= 1;
	var taskinterval	= 200;
	var taskpic			= "sitting.";
	var taskpicid		= 0;
	var taskxml			= null;
	var etask			= "";
	var tick1=0, tick2=0;
	loadTask("wave");
	//var.tasklist = Array;
	//var.taskcount = 0;
	//var.currenttask = 0;
	petobj.passport.callback = passportcallback;
	tick2=setTimeout(renderMood, 1000); //petobj.passport.clock);
	render();
	
	this.render = render;
	function render(){
		//return;
		if(petobj.running==false){ debug.trace("bailed out"); return; }
		if(petobj.mood.getMood("mood")<=0){ petobj.stopPet("petdied.gif","","pet is dead"); return; }		
		// setup a new timer
		if(taskinterval < 200) taskinterval = 200;
		tick1=setTimeout(render, taskinterval);
		// task specials
		/* moved to taskcomplete event */
		// set the pet image
		petobj.petimg.setImage(petobj.getPic(parseInt(taskpicid + taskframe) - 1));
		// move to next frame
		taskframe += taskdirection;
		// notify if task finished		
		if(taskframe < 1 || taskframe > taskframes) 
			eventhandler("taskdone",taskframe, taskframes, taskdirection); 
	}
	
	/*-------------------------
	  renderMood
	  slow timer, what keeps the pet in sync with the server mydigipet.com
	  1. works out new mood
	  2. saves mood as xml
	  3. sends new mood to server
	  4. gets server appid, which might meen the pet is at another desktop
	  -------------------------*/
	this.renderMood = renderMood;
	function renderMood(){
		if(petobj.running==false){ debug.trace("bailed out"); return; }
		var xml;
		petobj.mood.render();
		xml = petobj.mood.createMoodXML();
		petobj.passport.xml = xml;
		petobj.passport.getPassport();		
	}
	
	this.passportcallback = passportcallback;
	function passportcallback(){
		// check petobj.passport.home
		if(petobj.passport.petname=="") petobj.passport.petname=petobj.defaultname;
		if(petobj.passport.home) petobj.menu.homeVisible(false); else petobj.menu.homeVisible(true); 
		var lifeline = parseInt((petobj.passport.servertime - petobj.passport.dob)/3600)+1;
		//
		if(petobj.passport.petname=="") petobj.passport.petname=petobj.defaultname;
		if(compat_window)
			petobj.lblpetname.innerHTML = petobj.passport.petname + " age:"+lifeline;
		else
			petobj.lblpetname.innerText = petobj.passport.petname + " age:"+lifeline;
			
		tick2=setTimeout(renderMood, petobj.passport.clock);
	}
	
	this.eventhandler = eventhandler;
	function eventhandler(eventname, param1, param2,param3){
	var tmptask = "";
	var events = null;
	switch(eventname){
		case 'onload':
			loadTask("sit");
			break;
		case 'taskload':
			if(taskdirection!=1) return;
			// check pre-conditions: i.e: if task is eat, make sure some foods out....
			// make object invisible if in use?
			
			var allow=true;
			var value=0;
			var tmpobj=null;
			var etype="", ename="", echange=0; 
			var events = taskxml.getElementsByTagName("event");
			for(var i=0; i<events.length; i++){
				//debug.trace(task+" "+taskframe+" "+taskframes+" "+i+" "+taskdirection);
				if(!(etype=events[i].getAttribute("type"))) etype="";
				if(!(ename=events[i].getAttribute("name"))) ename="";
				if(!(echange=events[i].getAttribute("change"))) echange=0; else echange=parseInt(echange);
				switch(etype){
					case 'objectvalue': 
						if(echange < 0){
							tmpobj = petobj.petobjects.getObjectByName(ename);
							if(tmpobj!=null){
								value = parseInt(tmpobj.getValue());
								if(value==0) allow=false; else tmpobj.setVisible(false);
							}
						}
						break;
				}
			}
			if(!allow){
				clearJobList();
				loadTask("sit");
			}
			break;
		case 'taskdone': 
			// task specials (EVENT ELEMENTS)

			var value=0;
			var tmpobj=null;
			var etype="", ename="", echange=0; 
			var events = taskxml.getElementsByTagName("event");
			if(etask == task){
			for(var i=0; i<events.length; i++){
				if(!(etype=events[i].getAttribute("type"))) etype="";
				if(!(ename=events[i].getAttribute("name"))) ename="";
				if(!(echange=events[i].getAttribute("change"))) echange=0; else echange=parseFloat(echange);
				switch(etype){
					case 'objectvalue': 
						if(taskdirection==1){
						tmpobj = petobj.petobjects.getObjectByName(ename);
						if(tmpobj!=null){
							value = parseInt(tmpobj.getValue());
							value += echange;
						//debug.trace("changing object value:"+ename+" "+value);
							if(value<=0){ value=0; tmpobj.setVisible(false); }else{ tmpobj.setVisible(true); }
							tmpobj.setValue(value);
						}
						}
						break;
					case 'mood': 
						if(taskdirection==1){
			//debug.trace("done "+task+" "+taskframe+" "+taskframes+" "+taskdirection+" "+i+" "+ename);							
						value = parseFloat(petobj.mood.getMood(ename));
						value+=echange;
						//debug.trace("changing mood:"+ename+" "+value);
						petobj.mood.setMood(ename,value);
						}
						break;
					case 'objectmovex': break;
					case 'objectmovey': break;
					
				}
			}
			}
			tmptask = popJob();
			if(tmptask==""){
				// task actions (ACTION ELEMENT)
				/* needed? could be used to make sitting do less boring things? 
				   1. action element is depreciated in favor of event element
				   2. dojob forces back to sitting so only sitting task can read action element
				   3. action is still used to help doJob, navigate on event
				*/
				// load next ask
				clearJobList();
				tmptask="sit";
			}
			loadTask(tmptask);
			break;
		case 'moodchanged':
			if(currentJob < jobCount) return;
			//REFLEXT RESPONCE, if hungry... eat!
			if(parseInt(param2) < parseInt(param3)){
				events = xmlobj.getElementsByTagName("event");	
				for(var i=0; i<events.length;i++){
					if(events[i].getAttribute("type")=="mood"){
						if(events[i].getAttribute("name")==param1){
							if(parseInt(events[i].getAttribute("change")) > 0){
								doJob(events[i].parentNode.tagName.substring(4),false);
								return;
							}
						}
					}
				}
			}
			//FORCED RESPONCE (rare i prefer to keep pets flexible)
			/*	taskname is equal to the whole event name
				attribiture(change) relates to the current mood value
				because of xml rools:
				++ = >
				-- = <
			*/
			events = xmlobj.getElementsByTagName("on"+eventname+param1);
			var attrchange,sign="",parentjob;
			for(var i=0; i<events.length;i++){
				parentjob=events[i].parentNode.tagName.substring(4);
				attrchange = events[i].getAttribute("change");
				
				if(attrchange.length >= 2){
					sign = attrchange.substring(0,2);
					if(sign=="--"){ sign = "<"; attrchange = attrchange.substring(2); }
					if(sign=="++"){ sign = ">"; attrchange = attrchange.substring(2); }					
				}
				attrchange = parseInt(attrchange);
				switch(sign){
					case "<": if(param2 < attrchange) doJob(parentjob,false); break;
					case ">": if(param2 > attrchange) doJob(parentjob,false);  break;
					case "": if(param2 == attrchange) doJob(parentjob,false);  break;
				}
				
			}
		break;
		case 'submenubutton':
		
		break;
		case 'objectadded':
		
		break;
		case 'objectremoved':
		
		break;
		case 'objectclicked':
			if(param3=="1" || jobCount < 1) doJob(param2,false);
		break;
	}
	}

	this.loadTask = loadTask;
	function loadTask(taskname){
		debug.trace("load: "+taskname);
		taskxml=null;
		var d = taskname.substring(0,1);
		var dir=1;
		if(d=="+") taskname = taskname.substring(1);
		if(d=="-"){ taskname = taskname.substring(1); dir=-1; }
		task=taskname ;
		taskdirection=dir;	
		taskxml = xmlobj.getElementsByTagName('task'+taskname);
		etask=taskname;
		taskxml = taskxml[0];
		for(var i=0; i<taskxml.childNodes.length; i++){
			switch(taskxml.childNodes[i].tagName){
				case "picid": 	taskpicid 	= parseInt(taskxml.childNodes[i].firstChild.nodeValue); break;
				case "pic": 	taskpic 	= taskxml.childNodes[i].firstChild.nodeValue; break;
				case "speed": 	taskinterval= taskxml.childNodes[i].firstChild.nodeValue; break;
				case "frames":	taskframes 	= parseInt(taskxml.childNodes[i].firstChild.nodeValue); break;
				case "parent":  break;
				case "actions": break;
			}
		}
		//debug.trace(taskname+": "+taskframes+" "+taskpicid);
		if(taskinterval < 200) taskinterval=200;
		if(taskdirection==1) taskframe = 1; else taskframe = taskframes;
		eventhandler("taskload","","","");
		return true;
	}

	this.destroy=destroy;
	function destroy(){
		clearTimeout(tick1);
		clearTimeout(tick2);		
	}
	/*------------------
	  JOB HANDLERS/LISTS
	  responsponsible for moothing smoothly from one animation to the other.
	  ----------------------*/
	this.pushJob = pushJob;
	function pushJob(newtask){
		jobList[jobCount] = newtask;
		jobCount++;
	}
	
	this.popJob = popJob;
	function popJob(){
		var cj = "";
		if(currentJob < jobCount){
			cj = jobList[currentJob];
			currentJob++;
			cleanJobList();
		}
		return cj; 
	}
	
	this.clearJobList = clearJobList;
	function clearJobList(){
		jobCount=0;
		currentJob=0;
		jobList = new Array();
	}
	
	// check math for errors!
	this.cleanJobList = cleanJobList;
	function cleanJobList(){
		if(currentJob > 20){
			for(var i=0; i<jobCount-20; i++){
				jobList[i] = jobList[i+19];	
			}
			jobCount=jobCount-20;
			currentJob=currentJob-20;
		}
	}
	/*-------------------------------------------------------------------
	creates a job list so the pet can move smoothly from one task to the next */
	function jobAllowed(task){
		var allow=true;
		var value=0;
		var tmpobj=null;
		var stripTask=task;	
		if(remPlus(stripTask)!="") stripTask = stripTask.substring(1); 
		var etype="", ename="", echange=0; 
		var tmpxml = xmlobj.getElementsByTagName("task"+stripTask);
		tmpxml = tmpxml[0];
		var events = tmpxml.getElementsByTagName("event");
		for(var i=0; i<events.length; i++){
			if(!(etype=events[i].getAttribute("type"))) etype="";
			if(!(ename=events[i].getAttribute("name"))) ename="";
			if(!(echange=events[i].getAttribute("change"))) echange=0; else echange=parseInt(echange);
			switch(etype){
				case 'objectvalue': 
					if(echange < 0){
						tmpobj = petobj.petobjects.getObjectByName(ename);
						if(tmpobj!=null){
							value = parseInt(tmpobj.getValue());
							if(value==0) allow=false; //else tmpobj.setVisible(false);
						}
					}
					break;
				case 'mood':
					if(echange < 0 && ename!="mood"){
						value = petobj.mood.getMood(ename);
						if(parseInt(value+echange) < 0) allow=false;
					}
					break;
			}
		}
		return allow;
	}
	
	this.doJob=doJob;
	function doJob(jobtask,clearjobs){
		//clearjobs=true;
		if(!jobAllowed(jobtask)) return false;
		if(clearjobs==true) clearJobList();
		var tmpArray = new Array();
		var ourtask=jobtask;
		for(i=0;i<10;i++){
			var tmp=getParent(ourtask);
			if(tmp==false) return false;
			if(tmp=="sit") i=15; else tmpArray[tmpArray.length]=tmp;
			ourtask=tmp;
		}
		if(i==16){
			for(i=tmpArray.length-1;i>=0;i--){
				pushJob(tmpArray[i]);
			}
			pushJob(jobtask);
			backToSitting();
			//if(jobtask=="eat") alert(jobList.join(" + "));
			return true;
		}
		return false;
	}

	// reverses through job loop, trying to find a way back to sitting
	// todo: reverse every + go to parent task
	// or:	 read actions check if parent==sit
	this.backToSitting=backToSitting;
	function backToSitting(){
		var jc = jobCount-1;
		var t = rpt = jobList[jc];		
		if(remPlus(rpt)!="") rpt = rpt.substring(1); 
		// check if sit action... on end of finishing task			
		var taskxml2 = xmlobj.getElementsByTagName("task"+rpt);
		taskxml2 = taskxml2[0];//what if task not found?
		actions = taskxml2.getElementsByTagName("action");
		for(var i=0; i<actions.length; i++){
			if(actions[i].getAttribute("task")=="sit"){
				pushJob("sit");	
				return;
			}
		}
		
		// loop up parents
		for(var bail=0; bail<10; bail++){
			var d = remPlus(t);
			if(d=="") d="+"; else t = t.substring(1); 
			if(d=="-"){
				t2=t;
				t=getParent(t);
				if(t=="sit"){ pushJob("sit"); return; }
				// check if sit action... on parent				
				taskxml2 = xmlobj.getElementsByTagName("task"+t);
				taskxml2 = taskxml2[0];//what if task not found?
				actions = taskxml2.getElementsByTagName("action");
				for(var i=0; i<actions.length; i++){
					if(actions[i].getAttribute("task")=="sit"){
						pushJob("sit");	
						return;
					}
				}
				t="-"+t;
			}else{
				t="-"+t;	
			}
			pushJob(t);
		}
		if(bail==10){ 
			debug.error("could not find way back to sitting!");
			jobList[jc+1] = "sit";
			jobCount=jc+2;
		}
	}
	
	/*pets.getParent(task)
	--------------------------------------------------------------
	gets the job to return to between then <parent></parent> tags. */
	function getParent(jobtask){
		if(remPlus(jobtask)!="") jobtask = jobtask.substring(1);
		var tmpnode = xmlobj.getElementsByTagName("task"+jobtask);
		tmpnode = tmpnode[0];
		tmpnode = tmpnode.getElementsByTagName("parent");
		if(tmpnode==null) return false;
		if(tmpnode[0]==null) return false;
		return tmpnode[0].firstChild.nodeValue;
	}

	function remPlus(jobtask){
		var d = jobtask.substring(0,1);
		if(d=="+") return "+";
		if(d=="-") return "-";
		return "";
	}

}
