module br.ship;

private import SDL_mixer;
private import opengl;
private import str = std.string;
private import std.math;
private import util.parts;
private import util.key;
private import util.shape;
private import util.vector;
private import util.matrix;
private import util.log;
private import util.beam;
private import util.particle;
private import br.shapeImpl;
private import br.screen;
private import br.mainloop;
private import br.gamemanager;
private import br.append;
private import br.blast;


public class Ship:Parts{
	
	//import br.mainloop;
	public:
	bool sword;
	bool slow;
	bool miss;
	
	private{
		Key key;
		int pressing;
		int reload;
		double gradient;
		int cPressed;
		double predegAim;
//		Vector3[100] rpos0;
//		Matrix[100] rpose0;
	}
	public this(){}
	public this(Key key,float x,float y){
		collisionManager.add(this ,collisionManager.kind.SHIP ,1);
		this.key = key;
		start(x ,y);
		Parts p;//Parts p;
//		for(int i=0;i<rpos0.length;i++){
//			rpos0[i] = new Vector3();
//			rpose0[i] = new Matrix();
//		}
		
		
		setBackColor(sword);
//		p = new LaserGun();//LaserGun();
		
		
		p = new Append(MyShipAppend.getShape().reverseZ() ,15 , 1.0 ,1.0 ,1.0 ,1.0);
		addChild(p, "append1", 20 ,ENGAGED ,matRotateY(140) * matRotateX(-10) ,matRotateY(-20));
		
		p.drawing = WIRE | POLYGON;
		p = new Append(MyShipAppend.getShape() ,15 , 1.0 ,1.0 ,1.0 ,1.0);
		p.drawing = WIRE | POLYGON;
		addChild(p, "append2", 20 ,ENGAGED ,matRotateY(-140) * matRotateX(10) ,matRotateY(20));
		
//		changeScale(3.0 ,true);
		shipManager.add(this);
//		shipManager.add(childHash["append1"]);
//		shipManager.add(childHash["append2"]);
		setColor(R ,G ,B ,alpha,true);
	}
	
	
	public void start(float x ,float y){
		pos = new Vector3(x ,y ,-800);
		rpos = cast(Vector3)pos.clone();
		Matrix po = new Matrix(); //matRotate(-90 ,0 ,0 ,1) * matRotate(45 ,1 ,0 ,0);
//		pos = new Vector3(x ,y ,-800);
		setPoseBase(po);
		
		poseZ = rposeZ = 0.0;
		linkZ = rlinkZ = 0.0;
		
		drawing =  WIRE | POLYGON;
		gradient = 0.0;
		size =  20;
		collisionRange = 10;
		R = 1.0;G =0.88;B = 0.7;alpha = 1.5;
		predegAim = 0.0;
		
		pressing = 0;
		reload = 0;
		cPressed = 0;
		slow = true;
		sword = true;
		miss = false;
		
		if("laserGun" in childHash)childHash["laserGun"].vanish();
		Parts p = new Sword(rpos ,0.0);
		addChild(p ,"laserGun" ,50 ,NORMAL);
		
		/*
		if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,4);
		}
		*/
	    shape = MyShip.getShape();//new SH_Pole(a ,b ,4);
		
		
		
		
	}
	public void setBackColor(bool sword){
		/*
		if(sword)screen.setClearColor(0.2 ,0.14 ,0.1 ,1.0);
		else screen.setClearColor(0.1 ,0.14 ,0.2 ,1.0);
		/*
		if(sword)screen.setClearColor(0.09 ,0.06 ,0.04 ,1.0);
		else screen.setClearColor(0.04 ,0.06 ,0.09 ,1.0);
		*/
	}
	public void addChild(inout Parts child,char[] name, double dist = 0.1, int childKind = NORMAL, Matrix link = null ,Matrix pose = null){
		super.addChild(child ,name ,dist ,childKind ,link ,pose);
		shipManager.add(child);
	}
	public void move(){
		super.move();
		assert(childs.length <= 3);
		double speed;
		int button = key.getButtonState();
		/*
		reload --;
		if(button & key.Button.A){
			if(reload <= 0 && Bullet.number < 20){
				for(int i = 0;i < 3;i ++){
					new Bullet(pos + (new Vector3(10 ,0 ,0)) ,(i - 1) * PI / 60.0);
				}
				//new Bullet(childHash["laserGun"].rpos ,childHash["laserGun"].linkZ * PI /180);
				pressing ++;
				reload = 3;
				//new Bullet(pos + (new Vector3(10 ,-10 ,0)) ,0);
			}
			//}
		}else pressing = 0;
		*/
		/*
		if(button & key.Button.A){
			
			if(childHash["laserGun"] !is null){
				(cast(Beam)childHash["laserGun"]).fixAim = true;
			}
		}else{
			if(childHash["laserGun"] !is null){
				(cast(Beam)childHash["laserGun"]).fixAim = false;
			}
		}
		*/
		
		if(((button & key.Button.A) != 0)){
			//if(cPressed <= 0){
			//sword ^= true;
			pressingA = true;
			if(sword){
			sword ^= true;
			
			double tempZ = childHash["laserGun"].rposeZ;
			//double tempSpeed = childHash["laserGun"].speed;
			if("laserGun" in childHash){
				childHash["laserGun"].vanish();
				childHash["laserGun"] = null;
			}
			Parts p;
			if(sword){
				p = new Sword(rpos ,tempZ);
				
			}else{
				p = new LaserGun(rpos ,tempZ);
			}
			setBackColor(sword);
			addChild(p ,"laserGun" ,50 ,NORMAL);
//			(cast(Beam)p).set(tempZ);
			}
			//}
			//cPressed = 1;
		//	p.speed = tempSpeed;
		}else{
			pressingA = false;
			if(!sword){ 
			sword ^= true;
			double tempZ = childHash["laserGun"].linkZ;
			//double tempSpeed = childHash["laserGun"].speed;
			if("laserGun" in childHash)childHash["laserGun"].vanish();
			Parts p;
			if(sword){
				p = new Sword(rpos ,tempZ);
				
			}else{
				p = new LaserGun(rpos ,tempZ);
			}
			setBackColor(sword);
			addChild(p ,"laserGun" ,50 ,NORMAL);
//			(cast(Beam)p).set(tempZ);
			}
//			 cPressed --;

		}
		slow = sword;
		/*
		if(((button & key.Button.B) != 0)){
			slow = false;
		}else slow = true;
		*/
//		if(pressing > 5)speed = 5.0;
//		else speed = 8.0;
		if(sword)speed = 6.8;
		else speed = 6.8;
		
		
		int dir = key.getDirState();
		int aim = 5;
		//Vector aim = new Vector(0,0);
		
		if(dir & Key.Dir.RIGHT){
//			if(!(button & key.Button.A))
			pos.x += speed;
			aim -= 1;
			//aim.x += 1;
		}
		if(dir & Key.Dir.LEFT){
//			if(!(button & key.Button.A))
			pos.x -= speed;
			aim += 1;
			//aim.x -= 1;
		}
		if(dir & Key.Dir.DOWN){
//			if(!(button & key.Button.A))
/*
			if(gradient < 20.0f){
				rotateAll(matRotateX(2.0f));
				gradient +=2.0f;
			}
			*/
			pos.y -= speed;
			aim -= 3;
			//aim.y -= 1;
		}else if(dir & Key.Dir.UP){
//			if(!(button & key.Button.A))
/*
			if(-20.0 < gradient){
				rotateAll(matRotateX(-2.0f));
				gradient -=2.0f;
			}
			*/
			pos.y += speed;
			aim += 3;
			//aim.y += 1;
		}else{
			/*
			if(gradient < -1.0){
				gradient +=1.0f;
				rotateAll(matRotateX(1.0f));
			}else if(1.0 < gradient){
				gradient -=1.0f;
				rotateAll(matRotateX(-1.0f));
			}else poseX =0.0f;
			*/
		}
		
		double degAim;
		bool moved = true;
		switch(aim){
			case 1:degAim=135.0;		break;
				case 2:degAim=90.0;		break;
				case 3:degAim=45.0;		break;
				case 4:degAim=180.0;	break;
				case 6:degAim=0.0;		break;
				case 7:degAim=-135.0;	break;
				case 8:degAim=-90.0;	break;
				case 9:degAim=-45.0;	break;
				case 5:
				default:
				degAim = predegAim;
				moved = false;
				break;
		}
		predegAim = degAim;
		if(childHash["laserGun"] !is null){
			(cast(Beam)childHash["laserGun"]).setAim(degAim ,true);//moved);
		}
		
		if(pos.y < screen.GAME_DOWN + size)pos.y = screen.GAME_DOWN + size;
		if(screen.GAME_UP - size < pos.y)pos.y = screen.GAME_UP - size;
		if(screen.GAME_RIGHT - size < pos.x)pos.x = screen.GAME_RIGHT - size;
		if(pos.x < screen.GAME_LEFT + size)pos.x = screen.GAME_LEFT + size;
		
		//rotateAll(matRotateY(1 ) );
		
		//glLineWidth(1);
		
		
		//super.draw();
		
	}
/*
	public void drawImpl(){
		for(int i=0;i<rpos0.length-1;i++){
			drawLocus(shape ,rpos0[i] ,rpos0[i+1] ,rpose0[i] ,rpose0[i+1] ,R*0.5 ,G ,B ,1.0);
		}
		drawLocus(shape ,rpos ,rpos0[0] ,rpose ,rpose0[0] ,R*0.5 ,G ,B ,1.0);
		
		for(int i=rpos0.length-2;0<=i;i--){
			rpos0[i+1] = cast(Vector3)rpos0[i].clone();
			rpose0[i+1] = cast(Matrix)rpose0[i].clone();
		}
		rpos0[0] = cast(Vector3)rpos.clone();
		rpose0[0] = cast(Matrix)rpose.clone();
		
	}
*/
	public void reportCollision(int kind){
		
		destroy();
//		
		
		
	}
	public void destroy(){
		super.destroy();
		miss = true;
		makeParticle(shape, size ,WIRE ,rpos ,new Vector3() ,rpose ,R ,G ,B ,alpha);
		new SmallBlast(rpos.x ,rpos.y ,1 ,1 ,1000.0 ,60 ,R ,G ,B ,0.4);
		new SmallBlast(rpos.x ,rpos.y ,1 ,1 ,200.0 ,60 ,R ,G ,B ,0.2);
		
	}
	public double laserSpeed(){
		if(childHash["laserGun"] !is null)return (cast(Beam)childHash["laserGun"]).speed;
		return 0.0;
	}
	public double laserMaxSpeed(){
		if(childHash["laserGun"] !is null)return (cast(Beam)childHash["laserGun"]).maxSpeed;
		return 1.0;
	}
	public double laserMinSpeed(){
		if(childHash["laserGun"] !is null)return (cast(Beam)childHash["laserGun"]).minSpeed;
		return 1.0;
	}
}
public class LaserGun:Beam{
	private:
	static Shape baseShape;
	static float[] a =[
		-1.5 ,-1.2 ,1.5
	];
	static float[] b =[
		0 ,0.7 ,0.3
	];
	public:
	const uint MAXLOCUS = 30;
	public this(Vector3 pos ,double poseZ){
		super(10 ,pos ,poseZ);
		rolling = true;
		
//		shipManager.add(this);
		if(baseShape is null)baseShape = new SH_Pole(a ,b ,4);
		shape = cast(Shape)baseShape.clone();
		R = 1.0;G =0.95;B = 0.8;alpha = 1.5;
		locusR = 0.2;locusG = 1.0;locusB= 0.7;locusAlpha = 0.6;
		size = 10;
		collisionRange = 5;
		length = 1000;
		drawDist = 1;
		rootLength = 10;
		minSpeed = 9.0;maxSpeed = 9.0;accSpeed = 1.0;
		collisionManager.add(this, collisionManager.kind.LASER ,1 );
	}
	public void move(){
		super.move();
		if(parent is null)destroy();
		else if(!parent.exists)destroy();
	}
	public void draw(){
		glPushMatrix();
		super.draw();
		glPopMatrix();
		glEnable(GL_BLEND);
		glEnable(GL_LINE_SMOOTH);
		glPushMatrix();
		glTranslatef(rpos.x ,rpos.y ,rpos.z);
		glRotated(rposeZ ,0 ,0 ,1);
		glLineWidth(2);
		glBegin(GL_LINES);
		glColor4d(locusR,locusG,locusB,0.0);
		glVertex3f(0.0 ,0.0 ,0.0);
		glColor4d(locusR,locusG,locusB,locusAlpha);
		glVertex3f(100.0 ,0.0 ,0.0);
		glEnd();
		glColor4d(locusR,locusG,locusB,locusAlpha);
		glBegin(GL_LINES);
		glVertex3f(100.0 ,0.0 ,0.0);
		glVertex3f(length ,0.0 ,0.0);
		glEnd();
		glLineWidth(1);
		glPopMatrix();
		glDisable(GL_LINE_SMOOTH);
		glDisable(GL_BLEND);
		
		
	}
	public void destroy(){
		super.destroy();
		makeParticle(shape, size ,WIRE ,rpos ,new Vector3() ,rpose ,R ,G ,B ,alpha);
		new SmallBlast(rpos.x ,rpos.y ,20 ,20 ,10.0 ,60 ,R ,G ,B ,0.2);
	}
	public void setColor(double R ,double G ,double B ,double alpha){}
	/*
		public override void reportCollision(int kind){
			
	}
	*/
}
	


public class Sword:Beam{
	public:
	
	private:
	static Shape baseShape;
	static float[] a =[
		-0.1 ,0.0 ,0.1 ,0.5 ,2.0
	];
	static float[] b =[
		0.00 ,0.07 ,0.05 ,0.03 ,0.0
	];
	public this(Vector3 pos ,double poseZ){
		super(10 ,pos ,poseZ);
		rolling = true;

//		shipManager.add(this);
		if(baseShape is null)baseShape = new SH_Pole(a ,b ,4);
		shape = cast(Shape)baseShape.clone();
		R = 0.95;G =1.0;B = 0.9;alpha = 1.5;
		locusR = 0.2;locusG = 1.0;locusB= 1.0;locusAlpha = 1.3;
		size = 150;
		collisionRange = 5;
		length = 300;
		drawDist = 1;
		rootLength = 100;
		minSpeed = 15.0;maxSpeed = 15.0;accSpeed = 1.0;
		collisionManager.add(this, collisionManager.kind.SWORD ,1 );
	}
	public void move(){
		super.move();
		if(parent is null)destroy();
		else if(!parent.exists)destroy();
	}
	public void setColor(double R ,double G ,double B ,double alpha){}
	public override void reportCollision(int kind){
//		speed = fmax(0.0 ,speed - 1.0);
		//drawing = WIRE;
		
		
	}
	public void destroy(){
		super.destroy();
		makeParticle(shape, size ,WIRE ,rpos ,new Vector3() ,rpose ,R ,G ,B ,alpha);
		new SmallBlast(rpos.x ,rpos.y ,20 ,20 ,10.0 ,60 ,R ,G ,B ,0.2);
	}
	
}
