module br.bullet;

private import util.parts;
private import util.particle;
private import util.collision;
private import br.shapeImpl;
private import br.screen;
private import br.mainloop;
private import br.gamemanager;



public class Bullet:Parts{
	public:
	Vector3 vel;
//	int hp;
	public this(Vector3 pos){
		collisionManager.add(this ,collisionManager.kind.SHIP ,2);
		collisionManager.add(this ,collisionManager.kind.WALL ,2);
//		collisionManager.add(this ,collisionManager.kind.SHOT ,2);
		this.pos = cast(Vector3)pos.clone();
		rpos = cast(Vector3)pos.clone();
		
		drawing =  POLYGON | WIRE;
		R = 1.0;G =116.0f/255.0f;B = 122.0f/255.0f;alpha = 1.0;
		wR = 0.0;wG =0.0f;wB = 0.0f;walpha = 1.0;
		bulletManager.add(this);
		
//		hp = 3;
	}
	
	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 ||
			screen.GAME_NEAR < rpos.z - size || rpos.z + size < screen.GAME_FAR
			
		)){
			vanish();
		}
		
//		poseY += 1f;
	}
	public override void reportCollision(int kind ,Parts p){
		switch(kind){
			case CollisionManager.kind.SHIP:
			case CollisionManager.kind.WALL:
			destroy();
			break;
			
			default:break;
		}
		
	}
	public void destroy(){
		super.destroy();
//		makeParticle(shape, size ,WIRE ,rpos ,new Vector3() ,rpose ,R ,G ,B ,alpha);

	}
	
}

public class BulletAppend:Bullet{
	public this(float size = 20.0f,Shape shape = null ,Vector3 pos = new Vector3(0,0,0)){
		super(pos);
		if(shape !is null)this.shape = cast(Shape)shape.clone();
		else this.shape = BulletShape.getShape();
		this.size = size;
		collisionRange = size/2.0f;
		poseZ = 180;
	}
	public void move(){
		super.move();
		poseX += mulsp(2f);
		
		if(parent is null)destroy();
	}
}

public class Bullet1:Bullet{
	public:
	Vector3 vel;
	
	public this(Vector3 pos ,Vector3 vel){
		super(pos);
		this.vel = cast(Vector3)vel.clone();
		
		shape = BulletShape.getShape();
		size = 20.0f;
		collisionRange = 10.0f;
		poseZ = atan2(vel.y,vel.x)*180.0/PI;
	}
	public void move(){
		super.move();
		pos += mulsp(vel);
//		vel *= 1.02f;
		
		poseX += mulsp(2f);
	}
	
}
public class AccBullet:Bullet{
	public:
	Vector3 vel;
	Vector3 acc;
	float min;
	public this(Vector3 pos ,Vector3 vel ,Vector3 acc ,float min = 0.0f){
		super(pos);
		this.vel = cast(Vector3)vel.clone();
		this.acc = cast(Vector3)acc.clone();
		this.min = min;
		
		shape = BulletShape.getShape();
		size = 20.0f;
		collisionRange = 10.0f;
		poseZ = atan2(vel.y,vel.x)*180.0/PI;
	}
	public void move(){
		super.move();
		pos += mulsp(vel);
		vel += mulsp(acc);
		if(vel.size < min){
			vel = vec3Normalize(vel) * min;
		}
		
		poseX += mulsp(2f);
		poseZ = atan2(vel.y,vel.x)*180.0/PI;
	}
	
}

public class ReflectBullet:Bullet{
	public:
	Vector3 vel;
	int re;
	public this(Vector3 pos ,Vector3 vel){
		super(pos);
		this.vel = cast(Vector3)vel.clone();
		
		shape = BulletShape.getShape();
		size = 20.0f;
		collisionRange = 10.0f;
		
		poseZ = 180;
		re = 0;
		
		
	}
	public void move(){
		super.move();
		if(parent is null){
			pos += mulsp(vel);
	//		vel *= 1.02f;
			
			
			poseZ = atan2(vel.y,vel.x)*180.0/PI;
			re = cast(int)fmax(0,re-1);
		}
		poseX += mulsp(2f);
	}
	public override void reportCollision(int kind ,Parts p){
		if(parent is null){
			switch(kind){
				case CollisionManager.kind.SHIP:
				destroy();
				case CollisionManager.kind.WALL:
				if(re <= 0){
					if(vel.x<0)pos = new Vector3(p.pos.x+(p.collisionRange+collisionRange) ,pos.y ,pos.z);
					else pos = new Vector3(p.pos.x-(p.collisionRange+collisionRange) ,pos.y ,pos.z);
					vel = new Vector3(-vel.x ,vel.y ,vel.z);
					
					poseZ = atan2(vel.y,vel.x)*180.0/PI;
				}
				re ++;
				break;
				
				default:break;
			}
		}
		
	}
}
public class BlastBullet:Bullet{
	public:
	Vector3 vel;
	bool hit;
	bool right;
	public this(Vector3 pos ,Vector3 vel){
		super(pos);
		this.vel = cast(Vector3)vel.clone();
		
		shape = Octahedron.getShape();
		size = 20.0f;
		collisionRange = 10.0f;
		
		poseZ = 180;
		
		hit = false;
		right = false;
	}
	public void move(){
		super.move();
		if(parent is null){
			pos += mulsp(vel);
			if(hit){
				if(cnt % divsp(5) == 0){
					if(right){
						Vector3 vel = new Vector3(-6.0f ,0.0f ,0.0f);
						new AccBullet(rpos ,vel ,vel/-30.0f);
						new AccBullet(rpos-new Vector3(40.0f,0.0f,0.0f) ,vel ,vel/-30.0f);
//						new AccBullet(rpos-new Vector3(40.0f,0.0f,0.0f) ,vel ,vel/-30.0f);
					}else{
						Vector3 vel = new Vector3(6.0f ,0.0f ,0.0f);
						new AccBullet(rpos ,vel ,vel/-30.0f);
						new AccBullet(rpos+new Vector3(40.0f,0.0f,0.0f) ,vel ,vel/-30.0f);
//						new AccBullet(rpos+new Vector3(40.0f,0.0f,0.0f) ,vel ,vel/-30.0f);
					}
				}
			}
			
			poseZ = atan2(vel.y,vel.x)*180.0/PI;
		}
		poseX += 2f;
	}
	public override void reportCollision(int kind ,Parts p){
		if(parent is null){
			switch(kind){
				case CollisionManager.kind.SHIP:
				destroy();
				case CollisionManager.kind.WALL:
				if(!hit){
					if(vel.x<0){
						pos = new Vector3(p.pos.x+(p.collisionRange+collisionRange) ,pos.y ,pos.z);
						right = false;
					}else{
						pos = new Vector3(p.pos.x-(p.collisionRange+collisionRange) ,pos.y ,pos.z);
						right = true;
					}
					vel = new Vector3(0.0f ,-vel.size ,0.0f);
					
					poseZ = atan2(vel.y,vel.x)*180.0/PI;
				}
				hit = true;
				break;
				
				default:break;
			}
		}
		
	}
}

public class LockBullet:Bullet{
	
	public:
	Vector3 vel;
	Vector3 target;
	float speed;
	public this(Vector3 pos ,Vector3 vel ,Vector3 target ,float speed = 1.0f){
		super(pos);
		this.vel = cast(Vector3)vel.clone();
		this.target = cast(Vector3)target.clone();
//		this.min = min;
		this.speed = speed;
		shape = BulletShape.getShape();
		size = 20.0f;
		collisionRange = 10.0f;
		poseZ = atan2(vel.y,vel.x)*180.0/PI;
		
	}
	public void move(){
		super.move();
		pos += mulsp(vel);
		if(rpos.y>ship.rpos.y-20.0){
			Vector3 aim = target - rpos;
			double r = aim.size;
			if(r>0.0){
				vel += vec3Normalize(aim)/(r*r) * mulsp(16000.0f)*speed;
			}
			if(r < mulsp(100.0))pos += vec3Normalize(target - rpos)*mulsp(5.0f)*speed;
		}
		
		poseX += mulsp(2f);
		poseZ = atan2(vel.y,vel.x)*180.0/PI;
	}
	
	
	
}