function CurvesGame(canvas){
	var game=new CurvesGameClass(canvas);
	return game;
}

function CurvesGameClass(canvas){	
	DomNodeInterface(this);
	var me=this;
	this.canvas=canvas;
	this.board=null;

  
	this.runner=new Animator();
	this.runner.speed=20;	 
	this.rad=3;
	this.dia=this.rad*2+1;
	this.turnrate=5;
  
	this.rematchText="Press Space for rematch";
	this.rematchFont={size:"26pt",name:"Arial"};
  
	this.startText="Press Space for start";
	this.startFont={size:"26pt",name:"Arial"};

	this.helpText="Press H for the controls";
	this.helpFont={size:"16pt",name:"Arial"};
  
	this.playerText="Player 1 won";
	this.playerBox=null;
  
	this.highscoreurl="";
	this.highscores=[];
	this.length=0;  
}

CurvesGameClass.prototype.newPlayer = function(left, rigth, r, g, b){
	return {
		dead: false,
		left: left,
		right: rigth,
		score:0,
		turn: 0,
		loc:{
			x:0,
			y:0
		},
		dir: {
			x: 0,
			y: 0
		},
		strRGB:"rgb("+r+","+g+","+b+")",
		rgb: {
			r: r,
			g: g,
			b: b
		}
	};
};

CurvesGameClass.prototype.loadedHighScore = function(o){
	var score=o.getAsXML().documentElement.firstChild;
	while(score){
		this.highscores.push([score.getAttribute('name'),score.getAttribute('length')]);
		score=score.nextSibling;
	}
	
};

CurvesGameClass.prototype.appendedToParent = function(){
	this.init();
};

CurvesGameClass.prototype.init = function(){
    var me = this;
    var x=this.offsetAbsoluteLeft();
    var y=this.offsetAbsoluteTop();
    var w=this.getWidth();
    var h=this.getHeight();
    
	if (this.highscoreurl) {
		var call = new AjaxCall();
		call.url = this.highscoreurl + "?scores";
		call.onloaded = function(oCall){
			me.loadedHighScore(oCall);
		};
		AJAX.makeCall(call);
	}
	

	this.canvas.fillStyle("rgba(300,200,55,1)");
	this.canvas.fillRect(x,y,w,h);	
	var font = {
		size: "14px",
		name: 'verdana'
	};
	this.canvas.oFont(font);
	title_box = this.canvas.textBox("Curves Game");
	this.canvas.context.textBaseline = "top";
	this.canvas.fillStyle('rgb(0,0,0)');
	this.canvas.fillText("Curves Game", x + 2, y + 2);
	
	this.canvas.oFont(this.rematchFont);
	var rematchBox=this.canvas.textBox(this.rematchText);
	this.rematchTextX=x+(w-rematchBox.width)/2;
	this.rematchTextY=y+(h-rematchBox.height)/2;

	var playerBox=this.canvas.textBox(this.playerText);
	this.playerBox={x:x+(w-playerBox.width)/2,y:y+(h-rematchBox.height)/2-playerBox.height};	
	
	this.canvas.oFont(this.startFont);
	var startBox=this.canvas.textBox(this.startText);
	this.startTextX=x+(w-startBox.width)/2;
	this.startTextY=y+(h-startBox.height)/2;

	this.canvas.oFont(this.helpFont);
	var helpBox=this.canvas.textBox(this.helpText);
	this.helpTextX=x+(w-helpBox.width)/2;
	this.helpTextY=this.startTextY+startBox.height+2;	

			
	var font = {
		size: "10px",
		name: 'verdana'
	};
	this.canvas.oFont(font);
	this.score_box = this.canvas.textBox("000");
	
    //Create an instance of the apple being the circle.
	this.players=[];	
	this.player1=this.newPlayer(37,39,200,0,0);
	this.player2=this.newPlayer(65,68,0,200,0);
	this.player3=this.newPlayer(107,109,0,0,200);
	this.player4=this.newPlayer(100,12,0,200,200);
	this.player5=this.newPlayer(78,77,200,200,0);
	this.player6=this.newPlayer(57,48,200,0,200);				
	this.players.push(this.player1);
	this.players.push(this.player2);
		
	
	//Add key listener to the game.
	this.canvas.addListener(window,"keydown",function(e){me.onKeyDown(e);},false);
	
	//Add key listener to the game.
	this.canvas.addListener(window,"keyup",function(e){me.onKeyUp(e);},false);
	this.shape=new Array();
	for (var ly = 0; ly <this.dia; ly++) {			
		for (var lx = 0; lx <this.dia; lx++) {
			dx=Math.abs(lx-this.rad);
			dy=Math.abs(ly-this.rad);
			this.shape.push(Math.sqrt(dx*dx+dy*dy)<=this.rad);
		}
	}	
	this.board=new Rect({style:'clear',x:x+10,y:y+4+title_box.height,width:w-20,height:h-10-4-title_box.height});
	this.board.canvas=this.canvas;
	this.updateScore();
	this.rematch();					
};

CurvesGameClass.prototype.draw = function(){	
	
};
CurvesGameClass.prototype.reset = function(){		

	//Clear the board area of the canvas.
	this.board.draw();
	
	for(var index in this.players){
		this.players[index].score=0;
		this.players[index].dead=false;
	}
	this.updateScore();
	this.canvas.oFont(this.startFont);
    this.canvas.fillStyle('rgb(0,0,0)');
	this.canvas.fillText(this.startText,this.startTextX,this.startTextY);
	this.canvas.oFont(this.helpFont);
	this.canvas.fillText(this.helpText,this.helpTextX,this.helpTextY);	
};

CurvesGameClass.prototype.rematch = function(){
    var lx=this.offsetAbsoluteLeft();
    var ly=this.offsetAbsoluteTop();
    var lw=this.getWidth();
    var lh=this.getHeight();
	
	//Clear the board area of the canvas.
	this.board.draw();
	

	for(var index in this.players){
		this.players[index].loc.x=Math.floor(Math.random()*(this.board.width-40))+20+lx;
		this.players[index].loc.y=Math.floor(Math.random()*(this.board.height-40))+20+ly;
		this.players[index].dead=false;
		var deg=Math.PI/180*Math.random()*360;			
		var x = Math.cos(deg) *2;
		var y = Math.sin(deg) *2;
		this.players[index].dir.x = x;
		this.players[index].dir.y = y;		
	}
	//Set the function the animator calls each tick.
	var me=this;
	this.runner.call = function(){
		return me.run();
	};
  	this.length=0;	
	this.runner.start();  
};

CurvesGameClass.prototype.updateScore=function(){
    var x=this.offsetAbsoluteLeft();
    var y=this.offsetAbsoluteTop();
    var w=this.getWidth();
    var h=this.getHeight();
	
	var font = {
		size: "10px",
		name: 'verdana'
	};
	this.canvas.oFont(font);	
	var sbx=x+w-this.score_box.width-4;
	this.canvas.context.textBaseline="top";
	for(var index in this.players){
		this.canvas.clearRect(sbx-1,y+1,this.score_box.width+2,this.score_box.height+2);
		this.canvas.fillStyle(this.players[index].strRGB);
		this.canvas.fillText(this.players[index].score,sbx,y+2);
	   	sbx-=this.score_box.width+4;	
	}
	
};

CurvesGameClass.prototype.run=function(){
	var deg=Math.PI/180*this.turnrate;
    var runned=0;
	var id=0;
	for (index in this.players) {
		var player=this.players[index];
		//If dead ignore	
		if(player.dead){
			continue;
		}
		
		//If the player is turning, turn the direction vector.
		if (player.turn != 0) {
			var deg2=deg*player.turn;			
			var x = Math.cos(deg2) * player.dir.x - Math.sin(deg2) * player.dir.y;
			var y = Math.sin(deg2) * player.dir.x + Math.cos(deg2) * player.dir.y;
			player.dir.x = x;
			player.dir.y = y;
			
		}
        var l = {
			x: player.loc.x,
			y: player.loc.y
		};
		var d_old = this.canvas.getImageData(l.x, l.y, this.dia, this.dia);
		if(!d_old){
			return true;
		}

		var d_temp=this.canvas.createImageData(this.dia,this.dia);
		var i=0;
		for (var at = 0; at < d_old.data.length; at+=4,i++) {
			d_temp.data[at]=0;
			d_temp.data[at+1]=0;
			d_temp.data[at+2]=0;	
			d_temp.data[at+3]=0;							
		}		

		
        this.canvas.putImageData(d_temp,l.x,l.y);
		
		player.loc.x += player.dir.x;
		player.loc.y += player.dir.y;

		var d=this.canvas.getImageData(player.loc.x,player.loc.y,this.dia,this.dia);
		var i=0;
		for (var at = 0; at < d.data.length; at+=4,i++) {
			if(this.shape[i]){
				if(d.data[at+3]!=0){
					player.dead=true;
					break;
				}
				d.data[at]=player.rgb.r;
				d.data[at+1]=player.rgb.g;
				d.data[at+2]=player.rgb.b;
				d.data[at+3]=255;							
			}
		}
		this.canvas.putImageData(d,player.loc.x,player.loc.y);
		
		var d=this.canvas.getImageData(l.x,l.y,this.dia,this.dia);
		var i=0;
		for (var at = 0; at < d.data.length; at+=4,i++) {
			if(d_old.data[at+3]!=0){
				d.data[at]=d_old.data[at];
				d.data[at+1]=d_old.data[at+1];
				d.data[at+2]=d_old.data[at+2];	
				d.data[at+3]=255;							
			}
		}		
        this.canvas.putImageData(d,l.x,l.y);				
		

		runned++;	
		id=index;	    
	}  
	if(runned>1){
		this.length+=2;
		return true;
	}else{
	    var x=this.offsetAbsoluteLeft();
	    var y=this.offsetAbsoluteTop();
	    var w=this.getWidth();
	    var h=this.getHeight();
		
		id++;
		this.players[id-1].score++;
		this.updateScore();
		
		this.canvas.save();
		this.canvas.oFont(this.rematchFont);
		this.canvas.textAlign('center');
        this.canvas.fillStyle(this.players[id-1].strRGB);
		this.canvas.fillText(this.playerText.replace('1',id)+" Length:"+this.length,w/2,this.playerBox.y);		
        this.canvas.fillStyle('rgb(0,0,0)');
		this.canvas.fillText(this.rematchText,w/2,this.rematchTextY);
		this.canvas.oFont(this.helpFont);
		this.canvas.fillText(this.helpText,w/2,this.helpTextY);
		this.canvas.restore();
		
		return false;
	}
};

CurvesGameClass.prototype.help = function(){
    var x=this.offsetAbsoluteLeft()+10;
    var y=this.offsetAbsoluteTop()+15;

	var lines=[
	  ['The controls is as follows',0,0,0],
	  ['When out of game',0,0,0],
	  [' R resets the scores',0,0,0],
	  [' + adds a player and reset the score',0,0,0],
	  [' - removes a player and reset the score',0,0,0],
	  [' H gives you this help',0,0,0],
	  [' Space starts the game',0,0,0],
	  [' S gives you the high scores',0,0,0],	  
	  ['Player controls',0,0,0],
	  [' Player 1 uses the Left and Right arrow',this.player1.rgb.r,this.player1.rgb.g,this.player1.rgb.b],
	  [' Player 2 uses the A and D',this.player2.rgb.r,this.player2.rgb.g,this.player2.rgb.b],
	  [' Player 3 uses the + and -',this.player3.rgb.r,this.player3.rgb.g,this.player3.rgb.b],
	  [' Player 4 uses the 4 and 6 numpad',this.player4.rgb.r,this.player4.rgb.g,this.player4.rgb.b],
	  [' Player 5 uses the N and M',this.player5.rgb.r,this.player5.rgb.g,this.player5.rgb.b],
	  [' Player 6 uses the 9 and 0',this.player6.rgb.r,this.player6.rgb.g,this.player6.rgb.b]  	  	  	  
	];
	this.canvas.oFont(this.helpFont);	
	for(var i in lines){
		var box=this.canvas.textBox(lines[i][0]);
				
		this.canvas.fillStyle("rgb("+lines[i][1]+","+lines[i][2]+","+lines[i][3]+")");
		this.canvas.fillText(lines[i][0],x,y);		
		y+=box.height+2;
	}
};

CurvesGameClass.prototype.drawHighscores = function(){
    var x=this.offsetAbsoluteLeft()+10;
    var y=this.offsetAbsoluteTop()+35;
	
    this.canvas.oFont(this.helpFont);	
	var mx=0;	
	for(var i in this.highscores){
		var box=this.canvas.textBox(scores[i][0]);				
		this.canvas.fillStyle("rgb(0,0,0)");
		this.canvas.fillText(scores[i][0],x,y);		
		y+=box.height+2;
		mx=Math.max(mx,box.width);
	}
	var mx=this.x+10+mx;
	var y=this.board.y+35;	
	for(var i in this.highscores){
		var box=this.canvas.textBox(scores[i][0]);				
		this.canvas.fillStyle("rgb(0,0,0)");
		this.canvas.fillText(scores[i][1],mx+20,y);		
		y+=box.height+2;
		mx=Math.max(mx,box.width);
	}
	this.canvas.fillText("Name",x,this.board.y+10);
	this.canvas.fillText("Length",mx+20,this.board.y+10);
	this.canvas.moveTo(x,this.board.y+34);
	this.canvas.lineTo(mx+80,this.board.y+34);
	this.canvas.stroke();	
};

CurvesGameClass.prototype.onKeyDown=function(e){
	if (this.runner.isRunning()) {
		for (index in this.players) {
			if (this.players[index].left == e.keyCode) {
				this.players[index].turn = -1;
				return;
			}
			if (this.players[index].right == e.keyCode) {
				this.players[index].turn = 1;
				return;
			}
		}
	}else{
		if(e.keyCode==32){
			if (!e) var e = window.event;
			e.cancelBubble = true;
			if (e.stopPropagation){
				e.stopPropagation();
				e.preventDefault();
			} 
			this.rematch();
		}
		if(e.keyCode==107&&this.players.length<6){
			this.players.push(this['player'+(this.players.length+1)]);
			this.reset();
		}	
		if(e.keyCode==109&&this.players.length>2){
			alert(this.players);
			this.players.pop();
			this.reset();			
		}
		if(e.keyCode==82){
			this.reset();
		}	
		if(e.keyCode==72){
			this.help();
		}
		if(e.keyCode==83){
			this.drawHighscores();
		}							
	}	
};

CurvesGameClass.prototype.onKeyUp=function(e){	
	for (index in this.players) {
		if(this.players[index].left==e.keyCode&&this.players[index].turn==-1){
			this.players[index].turn=0;
			return;
		}
		if(this.players[index].right==e.keyCode&&this.players[index].turn==1){			
			this.players[index].turn=0;			
			return;
		}		
	}
};

if(typeof(JCanvasDSLClass)=='function'){
	JCanvasDSLClass.prototype.rootNode.gameCurves=function(self,node,parent){
		var ele=CurvesGame(self.canvas);
		self.mapAttributes(node,ele,[
				['x','x',parseInt],
				['y','y',parseInt],
				['color','rgb',self.colorSolver],
				['highscoreurl','highscoreurl'],				
				['width','width',function(w){return ele.setWidthByString(w);}],
				['height','height',function(h){return ele.setHeightByString(h);}]							
				]
		);	
		parent.appendChild(ele);
	};
}
