module br.bullet;
private import util.parts;
private import util.shape;
private import util.vector;
private import util.matrix;
private import util.log;
private import util.particle;
private import util.basis;
private import br.gamemanager;
private import br.blast;
private import std.math;
private import SDL_mixer;
private import br.sound;

public class Bullet:Parts{
	private bool inStage;
	public this(bool breakable){
		collisionManager.add(this ,collisionManager.kind.SHIP ,2);
		bulletManager.add(this);
		if(breakable){
			collisionManager.add(this, collisionManager.kind.LASER ,2);
			R = 160.0 / 255.0;
			G = 247.0 / 255.0;
			B = 150.0 / 255.0;
		}else{
			R = 245.0 / 255.0;
			G = 104.0 / 255.0;
			B = 110.0 / 255.0;
		}
		inStage = false;
		drawing = POLYGON | WIRE;
		alpha = 1.6;
	}
	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);
		bulletManager.add(child);
	}
	public void  move(){
		super.move();
		
		if((rpos.y+size < screen.GAME_DOWN || screen.GAME_UP < rpos.y-size ||
			screen.GAME_RIGHT  < rpos.x-size || rpos.x+size < screen.GAME_LEFT 
			
			)){
			if(inStage || 300 < cnt )vanish();
			
		}else inStage = true;
		
		
		if(screen.GAME_NEAR < rpos.z - size || rpos.z + size < screen.GAME_FAR){

			vanish();
		}
		
	}
	public void destroy(){
		super.destroy();
		new SmallBlast(rpos.x ,rpos.y ,30 ,30 ,5.0 ,90 ,R ,G ,B ,0.02);
//		makeParticle(shape, size ,WIRE ,rpos ,new Vector3() ,rpose ,R ,G ,B ,alpha * 0.5);
		makeSimpleParticle(2 ,size ,WIRE ,rpos ,R ,G ,B ,alpha * 0.5);
	}
	public override void reportCollision(int kind){
		destroy();
		
		Sound_PlaySe(se_kind.REVERSE);
//		Mix_PlayChannel(0, chunk_reverse, 0);
	}
	public void vanish(){
 		
		super.vanish();
	}
}

public class StraightBullet:Bullet{
	static Shape baseShape;
	static  float[][] a = 
		[
			[-2.0 ,0.0 ,1.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.0 ,0.0]
  	];
	double aim;
	double speed;
	public this(Vector3 v ,bool breakable, double aim ,double speed = 4.0){
		super(breakable);
		if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,4);
		}
//		setPoseBase(matRotateZ(aim / PI * 180.0));
		//collisionManager.add(this ,collisionManager.kind.BULLET ,2);
		
  	shape = new SH_Pole(a ,b ,4);
		size =  17;
		collisionRange = 8;
		this.speed = speed;
		
		pos = cast(Vector3)v.clone();
		rpos = cast(Vector3)pos.clone();
		this.aim = aim;
	}
	public void  move(){
		super.move();
		if(parent is null){
			pos.x += speed * cos(aim);
			pos.y += speed * sin(aim);
		}
		poseZ = aim / PI * 180.0;
	}
}
public class SlowStraightBullet:StraightBullet{
	public this(Vector3 v ,bool breakable, double aim){
		super(v ,breakable ,aim);
		speed = 1.5;
	}
}
public class EBullet2:StraightBullet{
	public this(Vector3 v ,bool breakable,double aim){
		
		super(v ,breakable ,aim);
		Parts b = new StraightBullet(v ,breakable ,aim);
		addChild(b ,"bul" ,40 ,FOLLOW);
		Parts b2 = new StraightBullet(v ,breakable, aim);
		b.addChild(b2 ,"bul" ,40 ,FOLLOW);
	}
}
public class Bullet3D:StraightBullet{
	public this(Vector3 v ,bool breakable,double aim ,double speed){
		
		super(v ,breakable ,aim ,speed);
	}
	public void move(){
		
		if(rpos.z < -800 - 2)pos.z +=2.0;
		else if(-800 + 2 < rpos.z)pos.z -= 2.0;
		else {
			super.move();
		}
		poseZ = aim / PI * 180.0;
	}
}
public class Bullet3D2:Bullet{
	static Shape baseShape;
	static  float[][] a = 
		[
			[-1.0 ,0.0 ,1.0]
  	   ];
  	static float[][] b =
		[
			[0.0 ,1.0 ,0.0]
  	];
	Vector3 aim;
	public this(Vector3 v ,bool breakable,Vector3 aim){
		super(breakable);
		if(baseShape is null){
			baseShape = new SH_Pole(a ,b ,4);
		}
//		setPoseBase(matRotateZ(aim / PI * 180.0));
		//collisionManager.add(this ,collisionManager.kind.BULLET ,2);
		
	  	shape = new SH_Pole(a ,b ,4);
		size =  25;
		collisionRange = 12;
		pos = cast(Vector3)v.clone();
		rpos = cast(Vector3)pos.clone();
		this.aim = cast(Vector3)aim.clone();
	}
	public void move(){
		super.move();
		pos += aim;
		
		poseZ += 1.0;
	}
}
public class BendBullet:StraightBullet{
	private:
	double bendAim;
	int bendTime;
	double afSpeed;
	public this(Vector3 v ,bool breakable,double aim ,double bendAim ,int bendTime,double speed = 4.0 ,double afSpeed = 4.0){
		super(v ,breakable ,aim ,speed);
		this.bendAim = bendAim;
		this.bendTime = bendTime;
		this.afSpeed = afSpeed;
	}
	public void move(){
		super.move();
		if(cnt == bendTime){
			aim += bendAim;
			speed = afSpeed;
		}
//		poseZ = aim/PI*180.0;
	}
}
public class AccBullet:StraightBullet{
	double maxSpeed ,accSpeed;
	public this(Vector3 v ,bool breakable,double aim ,double min ,double max ,double acc){
		
		super(v ,breakable ,aim ,min);
		maxSpeed = max;
		accSpeed = acc;
	}
	public void move(){
		super.move();
		if(speed < maxSpeed)speed += accSpeed;
		else speed = maxSpeed;
	}
}

public class HomingBullet:StraightBullet{
	private:
	double dAim;
//	int bendTime;
//	double afSpeed;
	public this(Vector3 v ,bool breakable,double aim ,double dAim = PI / 90.0,double speed = 4.0 ,int num = 1){
		super(v ,breakable ,aim ,speed);
		this.dAim = dAim;
		num--;
		if(0<num){
			Parts p = new HomingBullet(v ,breakable ,aim ,dAim ,speed ,num);
			addChild(p, "f", 34 ,FOLLOW );
		}
	}
	public void move(){
		
		super.move();
		if(parent is null){
			double taim = atan2(ship.rpos.y-rpos.y ,ship.rpos.x-rpos.x);
			if(abs(aim -taim) < dAim){}
			else if(raimmark(aim ,taim) < 0)aim -= dAim;
			else aim += dAim;
			
			aim = radlimit(aim);
			
			poseZ = aim*180.0/PI;
		}
//		poseZ = aim/PI*180.0;
	}
}