module es.ship;

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


class Ship{
  public const real RECMAX = 100;
  public const real SPEED = 7.0;
  public const int MAXSHIELD = 5;
  public real x , y ,z;
  public real fx ,fy ,fz;
  private real sx, sy, sz;
  public real size;
  public real[MAXSHIELD] px;
  public real[MAXSHIELD] py;
  public real[MAXSHIELD] pz;
  public real[MAXSHIELD] psize;
  public real[2] aim;
  public Gun gun;
  public int shield;
  public real recGauge;
  public int recCnt;
  public int damCnt;
  public bool recovering;
  public private Shape shape;
  public private real dam;
  public private int invTime;
  public this(){
    gun = new Gun();
    start();
    real[] a = [-10 ,-20 ,30, 40 ,20 ,-5 ,5 ,30];
    real[] b = [0 ,20 ,30 ,25 ,23 ,15 ,5 ,0];
    shape = new Symmentry(a ,b ,4);
  }
  public void start(){
    gun.start();
    aim[0] = 1.0;
    aim[1] = 0.0;
    x = 0;
    y = 0;
    z = 0;
    size = 1.0;
    for(int i = MAXSHIELD -1;0 <= i;i --){
      px[i] = x;
      py[i] = y;
      pz[i] = z;
      psize[i] = size;
    }
    fx = 0;
    fy = 0;
    fz = 0;
	sx=0;
	sy=0;
	sz=0;
    dam = 0;
    damCnt = 0;
    invTime = 0;
    shield = MAXSHIELD;
    recGauge = 0;
    recCnt = 0;
    recovering = false;
  }
   public void move(){
    for(int i = MAXSHIELD -1;1 <= i;i --){
      px[i] = px[i-1];
      py[i] = py[i-1];
      pz[i] = pz[i-1];
      psize[i] = psize[i-1];
    }
    px[0] = x;
    py[0] = y;
    pz[0] = z;
    psize[0] = size;
    real pox = pointer.fx;
    real poy = pointer.fy;
    real r = dist(fx ,fy ,pox ,poy );
    real r1 = 70;
    real r2 = 150;
    if(0.0 < r){
      aim[0] = (pox - x) / r;
      aim[1] = (poy - y) / r;
      if(r < r1){}
      else{ 
        if(r < r2){
          fx += aim[0] * SPEED;
          fy += aim[1] * SPEED;
        }else{
          fx += aim[0] * SPEED * 2.0;
          fy += aim[1] * SPEED * 2.0;
        }
      }
      
    }
    real fr = dist(fx ,fy ,field.x ,field.y );
	
    if(field.radius < fr){
      fx = (fx -field.x) * (field.radius / fr) + field.x;
      fy = (fy -field.y) * (field.radius / fr) + field.y;
    }
	
    x = field.transX(fx ,fy ,fz);
    y = field.transY(fx ,fy ,fz);
    z = field.transZ(fx ,fy ,fz);
    size = 0.8 + cast(real)(TEMPO - GameManager.count % TEMPO) / cast(real)TEMPO  * 0.2 * fmax(cast(real)shield ,0.0) / cast(real)MAXSHIELD;
    
	
    cam.update();
    
	
	if(dam > 0)dam -= 1.0f;
    else dam = 0;
    if(invTime > 0)invTime --;
    else invTime = 0;
	
	if(recovering){
     recCnt --;
     if(recCnt <= 0){
       recovering = false;
       shield ++;
     }
	}
	if(0 < damCnt){
     damCnt --;
	}
	
	sx = dam * rand.nextFloat(5.0f);
    sy = dam * rand.nextFloat(5.0f);
    sz = dam * rand.nextFloat(5.0f);
	
	gun.move(aim);
  }
  public void draw(){
  	cam.setCamera();

  	real r1 = 70;
    real r2 = 150;
  	
	real sc = screen.SCREEN_HEIGHT / 480.0;
    glScaled(sc, sc, sc);
    glPushMatrix();
//    x = mousex;
//    y = mousey;
    real[] ax = shape.x;
    real[] ay = shape.y;
    real[] az = shape.z;
    
    
   if(recovering){
     
     glPushMatrix();
     glColor3d(0.5,0.5,0.5);
     glTranslated(x ,y ,z );
     
	 sc = sqrt(cast(real)(recCnt * 10 + 1));
     glScaled(sc * 20.0, sc * 20.0, sc * 20.0);
	 
	 drawShipShape();
	 
//     sphereDetail(4);
//     sphere(20);
	 
     glPopMatrix();
    }
    if(0 < damCnt){
     glPushMatrix();
     glColor3d(0.5,0.5,0.5);
     
     glTranslated(x ,y ,z );
     
	 sc = sqrt(cast(real)((30 - damCnt) * 20 + 1));
     glScaled(sc * 20.0, sc * 20.0, sc * 20.0);
	 drawShipShape();
	 
	 /*
     sphereDetail(4);
     sphere(20);
	 */
     glPopMatrix();
   }
	 
    real co = (155.0 + (fmax(shield  ,0.0) * 100 / MAXSHIELD)) / 255.0;
    glColor3d(co, co, co);
     
    glTranslated(x ,y ,z );
    
   if(shield < MAXSHIELD){
   	glColor3d(1,1,1);
	arc(0 ,0 ,r1  ,r1 ,PI / 2.0 ,(PI / 2 + 2.0*PI / cast(real)(MAXSHIELD) * cast(real)shield));
	glColor3d(0.5,0.5,0.5);
	arc(0 ,0 ,r1  ,r1 ,(PI / 2 + 2.0*PI / cast(real)(MAXSHIELD) * cast(real)shield) ,PI / 2 + 2.0*PI);
   }else{
   	glColor3d(1,1,1);
   	arc(0 ,0 ,r1  ,r1);
   }
    
    if(0 < recGauge){
		glColor3d(0.5,0.5,0.5);
      arc(0 ,0 ,r2  ,r2  ,(PI / 2.0 - 2.0*PI / RECMAX * recGauge) ,(PI / 2 - 2.0*PI),PI / 180.0 * 3.0);
      glColor3d(1,1,1);
      arc(0 ,0 ,r2  ,r2  ,(PI / 2.0) ,(PI / 2.0 - 2.0*PI / RECMAX * recGauge),PI / 180.0 * 3.0);
      
    }else{
      glColor3d(0.5,0.5,0.5);
      arc(0 ,0 ,r2  ,r2 ,0.0, PI * 2.0 ,PI / 180.0 * 3.0);
    }
	co = (155.0 + (fmax(shield  ,0.0) * 100 / MAXSHIELD)) / 255.0;
    glColor3d(co, co, co);
    glTranslated(sx ,sy ,sz);
    glScaled(size * 20.0, size * 20.0, size * 20.0);
	
	drawShipShape();
	
//    sphereDetail(4);
//    sphere(20);
    glColor3d(1,1,1);
    
    gun.draw();
    
	
	glPopMatrix();
  }
  
  public void inTitle(bool onStart){
    fx = 0;
    fy = 0;
    fz = 0;
    real sx = dam * rand.nextFloat(5.0f);
    real sy = dam * rand.nextFloat(5.0f);
    real sz = dam * rand.nextFloat(5.0f);
    real r1 = 70;
    real r2 = 150;
    x = field.transX(fx ,fy ,fz);
    y = field.transY(fx ,fy ,fz);
    z = field.transZ(fx ,fy ,fz);
    cam.update();
    cam.setCamera();
	
	real sc=screen.SCREEN_HEIGHT / 480.0;
    glScaled(sc,sc,sc);
    if(onStart){
		size = 0.8 + cast(real)(TEMPO - GameManager.count % TEMPO) / cast(real)TEMPO  * 0.2 * fmax(cast(real)shield ,0) / cast(real)MAXSHIELD;
    }else{
 	   size = 0.8 + cast(real)((TEMPO*2) - GameManager.count % (TEMPO*2)) / cast(real)(TEMPO*2)  * 0.2 * fmax(cast(real)shield ,0) / cast(real)MAXSHIELD;
    }
    real[] ax = shape.x;
    real[] ay = shape.y;
    real[] az = shape.z;
    
    if(recovering){
     recCnt --;
     if(recCnt <= 0){
       recovering = false;
       shield ++;
     }
 
     glColor3d(0.5,0.5,0.5);
     glTranslated(x ,y ,z );
     glPushMatrix();
    
     sc = sqrt(cast(real)(recCnt * 10 + 1));
     glScaled(sc * 20.0, sc * 20.0, sc * 20.0);
	 drawShipShape();
//     sphereDetail(4);
//     sphere(20);
     glPopMatrix();
    }
    if(0 < damCnt){
     damCnt --;
     glPushMatrix();
     glColor3d(0.5,0.5,0.5);
     
     glTranslated(x ,y ,z );
     
     sc = sqrt(cast(real)((30 - damCnt) * 20 + 1));
	 glScaled(sc * 20.0, sc * 20.0, sc * 20.0);
	 drawShipShape();
//     sphereDetail(4);
//     sphere(20);
     glPopMatrix();
   }
    glTranslated(x ,y ,z );
    
   
    for(int i = MAXSHIELD - 1;0 <= i;i --){
      if(i < shield)glColor3d(1,1,1);
      else glColor3d(0.5,0.5,0.5);
      arc(0 ,0 ,r1  ,r1  ,(PI * 3.0 / 2.0 + 2.0 * PI / cast(real)MAXSHIELD * cast(real)i) ,(-PI / 2 + 2.0*PI / cast(real)MAXSHIELD * cast(real)(i + 1)));
    }
    if(0 < recGauge){
     glColor3d(1,1,1);
      arc(0 ,0 ,r2  ,r2 ,(PI / 2.0) ,(PI / 2.0 - 2.0*PI / RECMAX * recGauge));
      glColor3d(0.5,0.5,0.5);
      arc(0 ,0 ,r2 ,r2  ,(PI / 2.0 - 2.0*PI / RECMAX * recGauge) ,(PI / 2 - 2.0*PI));
    }else{
      glColor3d(0.5,0.5,0.5);
      arc(0 ,0 ,r2 ,r2 );
    }
	real co = (155 + fmax(shield  ,0) * 100 / MAXSHIELD)/255.0;
	if(!onStart){
		glColor3d(0.5,0.5,0.5);
	}else{
    	glColor3d(co, co, co);
	}
	glTranslated(sx ,sy ,sz);
    glScaled(size * 20.0, size * 20.0, size * 20.0);
    
	drawShipShape();
//    sphereDetail(4);
//    sphere(20);
    glColor3d(1,1,1);
    if(dam > 0)dam -= 1.0f;
    else dam = 0;
    if(invTime > 0)invTime --;
    else invTime = 0;
  }
  public void drawShipShape(){
  	real rad;
  	glBegin(GL_LINE_LOOP);
	for(rad=-PI;rad < PI;rad +=PI/4.0){
		glVertex3d(cos(rad),sin(rad),0.0);
	}
	glEnd();
	glBegin(GL_LINE_LOOP);
	rad=PI / 4.0 + PI / 2.0;
	glVertex3d(cos(rad),sin(rad),0.0);
	rad=PI / 4.0 + PI + PI / 2.0;
	glVertex3d(cos(rad),sin(rad),0.0);
	rad=PI / 4.0 + PI / 2.0 + PI / 2.0;
	glVertex3d(cos(rad),sin(rad),0.0);
	rad=-PI / 4.0 + PI / 2.0;
	glVertex3d(cos(rad),sin(rad),0.0);
	glEnd();
	
	glBegin(GL_LINES);
	glVertex3d(1.0 ,0.0,0.0);
	glVertex3d(-1.0 ,0.0,0.0);
	glEnd();
	
	glBegin(GL_LINES);
	glVertex3d(0.0 ,1.0,0.0);
	glVertex3d(0.0 ,-1.0,0.0);
	glEnd();
	
	glBegin(GL_LINE_LOOP);
	glVertex3d(1.0 ,0.0,0.0);
	rad=PI / 4.0 + PI / 2.0;
	glVertex3d(0.0,sin(rad),0.0);
	glVertex3d(-1.0 ,0.0,0.0);
	rad=PI / 4.0 + PI / 2.0 + PI / 2.0;
	glVertex3d(0.0,sin(rad),0.0);
	glEnd();
  }
  public void damage(real power){
    if(invTime <= 0){
      ep.allDamage(10);
      dam += power;
      damCnt = 30;
      shield --;
      invTime = 15;
    }
  }
  public void recPlus(real value){
    recGauge += value;
    if(RECMAX < recGauge && recovering == false){
      recovery();
      recGauge -= RECMAX;
    }
  }
  public void recovery(){
    if(shield < 5){
      recovering = true;
      recCnt = 30;
    }else shield = 5;
    
  }
}

public class Gun {
  private Shape shape;
  private int bulCnt;
  public Enemy lock;
  public this(){
    real[] a = [-10 ,0 ,18 ,30];
    real[] b = [0 ,10 ,6 ,0];
    shape = new Pole(a ,b ,5);
    
  }
  public void start(){
    bulCnt = 0;
    lock = null;
  }
   public void move(real[] aim){
    //System.out.println(lock);
    bulCnt --;
    
    if(mousePressed){
      bulCnt = 10;
    }else {
      lock = null;
      sp.release();
    }
    real[] daim =new real[2];
    real dtheta = 2.0*PI * (1.0 - rand.nextFloat(2.0)) / 30.0;
    daim[0] = aim[0] * cos(dtheta) + aim[1] * sin(dtheta);
    daim[1] = aim[1] * cos(dtheta) + aim[0] * sin(dtheta);
    if(0 <= bulCnt){
      if(lock !is null){
        if(lock.isExist() == false || lock.destroyed){
          sp.shot(ship.fx ,ship.fy ,daim[0] * 40.0f ,aim[1] *40.0f);
          lock = null;
        }else {
          real r = dist(ship.fx ,ship.fy ,lock.fx ,lock.fy );
          sp.shot(ship.fx ,ship.fy ,(lock.fx - ship.fx) / r * 40.0f ,(lock.fy - ship.fy) / r * 40.0f);
        }
      }
      else sp.shot(ship.fx ,ship.fy ,daim[0] * 40.0f ,daim[1] *40.0f);
    }
   }
   public void draw(){
   	real[] ax = shape.x;
    real[] ay = shape.y;
    real[] az = shape.z;
    if(lock !is null){
      glPopMatrix();
      glPushMatrix();
      glColor3d(1.0,1.0,1.0);
      
      
      glTranslated(lock.x + lock.sx,lock.y + lock.sy,lock.z + lock.sz);
      glLineWidth(4);
	  glBegin(GL_LINE_LOOP);
      glVertex3d(- 40 ,- 40 ,0);
	  glVertex3d(- 40 , 40 ,0);
	  glVertex3d( 40 , 40 ,0);
	  glVertex3d( 40 ,- 40 ,0);
	  glEnd();
      glLineWidth(1);
	  glPopMatrix();
    }

  }
}
