float STARTY = -100;
int PRELUDE_FALLS = 5;

class Fleet {
  int counter = 0;

  float x,  y;
           HashSet<Invader> invaders = new HashSet<Invader>();
  float left;
  float right;
  float bottom;
  float fleetwidth;
  
  int needToTouch = RIGHT;

  int mincol,maxcol,minrow,maxrow;
  int framecounter = 0;

  Fleet() {
    x = 20;
    y = STARTY;
      for(int r = 0; r < FLEET_ROWS ; r++) {
        for(int c = 0; c < FLEET_COLS; c++) {
        invaders.add(new Invader(0,0,this,r,c));
      }
    }
    updateInvaders();
  }
  
  boolean landed(){
    if(bottom > TANK_STARTY ){   
       return true;
    } else {
       return false; 
    }
  }
  
//figure out the width of the thing, the actual left and right side
  void computeSides(){
    boolean first = true;
       for(Invader i : invaders){
         if(! i.attacking){
       // i.identify();

           if(first){
        left = i.x - INVADER_OFFSET_X;
        right = i.x + INVADER_WIDTH + INVADER_OFFSET_X;
        bottom = i.y + INVADER_HEIGHT + INVADER_OFFSET_Y;
        mincol = i.col;
        maxcol = i.col;
        minrow = i.row;
        maxrow = i.row;
        first = false; 

       }
        left = min(left,i.x - INVADER_OFFSET_X); 
        right = max(right,i.x + INVADER_WIDTH+ INVADER_OFFSET_X);
        bottom = max(bottom, i.y + INVADER_HEIGHT + INVADER_OFFSET_Y);
        mincol = min(mincol,i.col);     
        maxcol = max(maxcol,i.col);     
        minrow = min(minrow,i.row);     
        maxrow = max(maxrow,i.row);     
         }
     } 
     
     fleetwidth = right - left;
     
   //  println(maxrow);
  }

  
  //put all the invaders correct relative to the location of the whole fleet
  void updateInvaders(){
    for(Invader i : invaders){
        i.doOffset(); //formation 
        //i.checkCollisions(); //now legions of invaders don't kill buildings
        //i.checkHitTank(); //now invaders in formation don't kill tank
     } 
     computeSides();
  }
  
    void animateInvaders(){
    for(Invader i : invaders){
        i.advanceFrame();
      } 
     computeSides();
  }
  
  
  void removeAll(Set<Invader> killed){
      invaders.removeAll(killed);
  }
  
  
  void move(){
    framecounter++;
    if(framecounter == 40){
        animateInvaders();
        framecounter = 0;
       }
    }

  void handleKey(int keyCode){    
     if(keyCode == LEFT){
   x-= FLEET_SIDEMOVE;
  }
  if(keyCode == RIGHT){
    x+=FLEET_SIDEMOVE;
  } 
  if(DEBUG == 1 && keyCode == DOWN){
     descend(); 
  }
  updateInvaders();
  computeSides();

  fixLeft();
  fixRight();
  
  
    if(keyCode == 32){
      //launch a random fighter from the bottom row
      if(hasInvadersInFormation()){
        fxDivebomb();
          launchRandomFromRow(maxrow);
      }
    }
  
  
    updateInvaders();
    
  }
  
 
boolean onDeck = false;
    
    
  void march(){    
 if(frameCount % 3 != 0 && (!isKeyDown(83))){
    return;
 } 
 if(onDeck) return;
 
    if(needToTouch == LEFT){
   x-= FLEET_SIDEMOVE;
  }
  if(needToTouch == RIGHT){
    x+=FLEET_SIDEMOVE;
  } 
  updateInvaders();
  computeSides();


   fixRight();
   fixLeft();

  if(y > STARTY + (FLEET_DOWNMOVE * PRELUDE_FALLS)){
     onDeck = true; 
  }
  
       updateInvaders();
  }
  

  





    
void fixRight(){
  if(right >= width){
    x -= (right - width);
     if(needToTouch == RIGHT){
        needToTouch = LEFT;
       descend(); 
     }
  }
  
    updateInvaders();
    
}
      
    
 
 void fixLeft(){
   if(left <= 0){ 
    x -= left;
    if(needToTouch == LEFT){
       needToTouch = RIGHT;
       descend();
    } 
  } 
 }
    
    
    
    
  

  void descend(){
//    println("GO DOWN");
     y +=  FLEET_DOWNMOVE;
     if(onDeck){
       numberOfFallsByPlayer++;
     }
     
  }
  
  
int numberOfFallsByPlayer = 0;
boolean hasDroppedOnce = false;
  
  void launchRandomFromRow(int whatrow){
    hasDroppedOnce = true;
    ArrayList<Invader> candidates = new ArrayList<Invader>();
    for(Invader i : invaders){
       if(! i.attacking && i.row == whatrow){
          candidates.add(i);
       } 
    }
    if(candidates.size() == 0){
        return;
    }
    int pick = (int)Math.floor(random(candidates.size()));
    Invader poorGuy = candidates.get(pick);
    launchInvader(poorGuy);
  }

  void launchInvader(Invader poorGuy){
   invaders.remove(poorGuy);
    invadersAttacking.add(poorGuy);
    poorGuy.attack(); 
  }


  boolean hasInvadersInFormation(){
     for(Invader i : invaders){
        if(!i.attacking) {
            return true;
        }  
     }
     return false;
  }
  
  
  
  void draw(){
    stroke(255); 
    /*line(0,0,x,y); 
    line(0,height,left,y);
    line(width,height,right,y);*/
     for(Invader i : invaders){
        i.draw();
     } 
  }
  
}