module es.shot;

private import std.math;
private import opengl;
private import es.shape;
private import es.basis;
private import es.gamemanager;
private import es.field;
private import es.enemy;


public Shape SHOT_SHAPE; 
public Shape SHOT_RING_SHAPE;
public real SHOT_MAXPOWER = 2.0;
public real SHOT_SIZE = 20.0;
public class Shot{
  private Shape shape;
  private Shape ring;
  public real fx ,fy ,fz;
  public real x ,y ,z;
  public real vx ,vy ,vz;
  public real power;
  private bool exist;
  private bool released;
  private int cnt;
  public this(real x ,real y ,real vx ,real vy ){
    // System.out.println("b");
    this.fx = x;
    this.fy = y;
    fz = 0;
    this.x = field.transX(fx ,fy ,fz);
    this.y = field.transY(fx ,fy ,fz);
    this.z = field.transZ(fx ,fy ,fz);
    this.vx = vx;
    this.vy = vy;
    exist = true;
    released = false;
    cnt = 0;
    power = SHOT_MAXPOWER;
    if(SHOT_SHAPE is null){
      real[] a = [-30 ,0 ,10, 20 ,30 ,40];
      real[] b = [0 ,10 ,15 ,20 ,15 ,5];
      SHOT_SHAPE = new Pole(a ,b ,6);
    }
    shape = cast(Shape)SHOT_SHAPE.clone();
    if(SHOT_RING_SHAPE is null){
      real[] a = [0 ,5 ,0 ,- 5 ,0];
      real[] b = [30 ,40 ,50, 40 ,30];
      
      SHOT_RING_SHAPE = new Pole(a ,b ,8);
    }
    ring = cast(Shape)SHOT_RING_SHAPE.clone();
  }
   public Enemy move(){
    // System.out.println("c");
    fx += vx;
    fy += vy;
    this.x = field.transX(fx ,fy ,fz);
    this.y = field.transY(fx ,fy ,fz);
    this.z = field.transZ(fx ,fy ,fz);
    
	Enemy lock = null;
    for(int i = ep.enemy.length - 1;0 <= i;i --){
     Enemy e = cast(Enemy)ep.enemy[i];
		if(e !is null){
	     if(dist(e.x ,e.y ,e.z ,x ,y ,z) < (SHOT_SIZE + e.largeness)){
	       real hp = e.damage(power);
	       if(power <= hp){
	         vanish();
	         if(released == false)
			 lock = e;
	       }
	     }
		}
     
    }
    if(cnt > 60)exist =false;
    cnt ++;
    return lock;
   }
   public void draw(){
   	if(cnt >= 1){
	   	glPushMatrix();
	   	real[] ax;
	    real[] ay;
	    real[] az;
	    if(cnt == 1){
	      ax = ring.x;
	      ay = ring.y;
	      az = ring.z;
	    }else{
	      ax = shape.x;
	      ay = shape.y;
	      az = shape.z;
	    }
	    glColor3d(1.0, 1.0, 1.0);
	    glTranslated(x , y , z);
	    if(vx > 0){
	      glRotated(atan(vy/vx)*180.0/PI , 0, 0, 1);
	    }else{
	      glRotated(atan(vy/vx)*180.0/PI + 180.0 , 0, 0, 1);
	    }
		glRotated(180.0 * GameManager.count / 20.0f , 1, 0, 0);
	   
	    //scale(0.7);
	    glBegin(GL_LINE_LOOP);
	    for(int i = 0; i < ax.length ;i ++){
	      glVertex3d(ax[i] ,ay[i] ,az[i]);
	    }
	    glEnd();
	    glPopMatrix();
   	}
  }
  public void vanish(){
    exist = false;
  }
  public bool isExist(){
    return exist;
  }
  public void release(){
    released = true;
  }
}
public class ShotPool{
	public:
	Shot[] shots;
	protected:
  	int shotIdx = 0;
	const int maxshot;
	public this() {
		
		maxshot = 16;
		shots.length = maxshot;
		shotIdx = 0;
		start();
	}

  public this(int n) {
		maxshot = n;
		shots.length = maxshot;
		shotIdx = 0;
		start();
  }
  public void start(){
  	clear();
   
  }
  public void clear(){
    foreach(inout Shot s;shots){
		if(s !is null){
			s.vanish();
		}
    }
	shotIdx = 0;
  }

	public bool shot(real x ,real y ,real vx ,real vy ){
		
    Shot s =new Shot(x ,y ,vx ,vy);
		
		for(int i = 0;i < shots.length;i ++){
			if(shots[shotIdx] is null || !shots[shotIdx].isExist()){
				shots[shotIdx] = s;
				return true;
			}
			shotIdx ++;
			if(shots.length <= shotIdx)shotIdx = 0;
		}
		
		return true;
	}
	public void move() {
		Enemy lock = null;
		Enemy lo;
		for (int i = 0;i < shots.length;i ++){
			Shot s = shots[i];
    		if (s !is null && s.isExist){
				
        		lo =s.move();
				if(s.isExist() == false)s = null;
      		}else{
	   		}
			if(lo !is null)lock = lo;
    	}
		if(ship.gun.lock is null && lock !is null)ship.gun.lock = lock;
	
  }


  public void draw() {
		
    for (int i = 0;i < shots.length;i ++){
		Shot s = shots[i];
      	if (s !is null && s.isExist()){
   	  		s.draw();
      }
    }
		
  }
  public void release(){
  	
    int i = shots.length - 1;
    while(0 <=i){
      Shot s = shots[i];
	  if(s !is null){
 	     s.release();
	  }
      i --;
    }
	
  }
  

}
/*
class ShotPool {
  private ArrayList shots;
   ShotPool(){
    init();
  }
   void init(){
    if(shots != null){
      shots.clear();
    }else shots = new ArrayList();
  }
   void shot(real x ,real y ,real vx ,real vy ){
    //System.out.println("a");
    Shot s =new Shot(x ,y ,vx ,vy);
    shots.add(s);
  }
   void update(){
    Enemy lock = null;
    int i = shots.size() - 1;
    
    while(0 <=i){
      Shot s = (Shot)shots.get(i);
      popMatrix();
      pushMatrix();
      
      Enemy lo = s.update();
      if(lo != null)lock = lo;
      if(s.exist == false){
        shots.remove(i);
      }
      i--;
    }
    if(ship.gun.lock == null && lock != null)ship.gun.lock = lock;
  }
  void release(){
    int i = shots.size() - 1;
    while(0 <=i){
      Shot s = (Shot)shots.get(i);
      s.release();
      i --;
    }
  }
}
*/