package MissileCommand;




public class Game extends GP.Containers.Row implements MCConstants {


  private GP.Containers.Frame _frame;
  private Turret[] _guns;
  private ButtonPanel _panel;
  private Mouse _mouse;
  private Attacker _attacker;
  private Holder _holder;
  private ShiftLeft _left;
  private ShiftRight _right;
  private AffiliationWin _aw;


  /** the constructor requires a container, because the GP.Containers.Row
    * needs to know where to draw itself.
    */
  public Game(GP.Container appletwindow) {
    
    /** in order to tell the superclass (GP.Containers.Row) about the container
      * this particular subclass is in, we pass it the appletwindow (see
      * Applet.java for more information)
      */
      super(appletwindow);


      /** make a new GP...Frame in "this," the GP.Containers.Row -- this is
	* so that the game actually has a container that can be manipulated to
        * play in (also sets size and color)
	*/
    _frame=new GP.Containers.Frame(this);
    _frame.SetSize(new GP.Attributes.Size(FRAME_SIZE_X,FRAME_SIZE_Y));
    _frame.SetColor(new GP.Attributes.Colors.Black());

    /** the holder pattern is a design that keeps track of many different
      * game attributes.  It is useful because without it, the parameter list
      * for many functions would be huge, and easy to screw up.  With the
      * holder, I just need one reference, and each class that "gets" the
      * holder has access to a ton of information.
      */
    _holder=new Holder(); // holder pattern model

    _guns=new Turret[NUM_TURRETS];

   
    /** Create an interface between the mouse and the program, and store a
      * a reference to it in the holder.  Now any class that has a reference
      * to the holder has a reference to the mouse interface, if they want it.
      */
    _mouse=new Mouse(_frame, _holder);
    _holder.SetMouse(_mouse);
    _mouse.TurnOn();

    this.initTurrets(); // draw and initialize the turret array
    _holder.setGunArray(_guns, DEFAULT_TURRET);
    this.initReactors(); // activate both keyinteractors
    
    _panel=new ButtonPanel(this, _holder);
    
    _holder.setGame(this);
    _aw=new AffiliationWin(_holder);

    _attacker=new Attacker(_frame, _guns, _mouse, _holder);
    
  }

  public void Start() {
   
    System.err.println("In start");
    for (int i=0; i<5; i++) {
      _guns[i].setColors();
    }

    _guns[DEFAULT_TURRET].Cycle();  // select the middle turret by default

    //_attacker.NewAttack(_guns[2]);
    //_attacker.NewAttack(_guns[0]);
    //_attacker.NewAttack(_guns[4]);
    
    this.newWave(1);

  }

  public void newWave(int level) {
    
    // basically 3 missiles per level
    System.err.println("in new wave");

    boolean gunsLeft=false;
    for (int i=0; i<NUM_TURRETS-1; i++) {
      gunsLeft=_guns[i].isValid();
      if (_guns[i].isValid()) break;
    }

    if (!gunsLeft) this.gameOver();

    else { // there are still turrets left -- keep the guns coming!
      for (int i=0; i<level*1; i++) {
	int rand=cs015.SP.RandomNumberFactory.RandomNumber(0,NUM_TURRETS-1);
	_attacker.NewAttack(_guns[rand]);
      }
    }


  }
      
  private void gameOver() {
    System.err.println("Game over, man!");
  }


  /** this method is private, since there's no real reason why any other class
    * would need to make key interactors.  The key interactors serve as an
    * interface between the program and the keyboard, assigning certain actions
    * to certain keystrokes.
    */
  private void initReactors() {
    _left=new ShiftLeft(_frame, "z", _holder);
    _left.TurnOnReactor();
    _right=new ShiftRight(_frame, "x", _holder);
    _right.TurnOnReactor();
  }


  /** again, this method is private since no one else needs to initialize the 
    * array of turrets.  It makes NUM_TURRETS new instances of Turret, and
    * sets their positions based on the current index of the for loop and
    * some offsets.  This way, only one line of code is required
    */
  private void initTurrets() {
    for (int i=0; i<NUM_TURRETS; i++) {
    _guns[i]=new Turret(_frame, _holder, new GP.Attributes.Position(TURRET_OFFSET+(TURRET_SPACING*i),FRAME_SIZE_Y), NUM_TURRETS);
    }
  }



}
