import java.util.*;
import java.io.*;
import javax.swing.JOptionPane;

/** 
 * The game class and it's sub-classes are very important game
 * initialization and the sequence of play.  A class digaram of the game class
 * can be found <a href="doc-files/GameGroup.html#classes">here</a>.  <br><br> Other
 * relevant documentation on the flow of the game sequence of play can be found
 * <a href="doc-files/GameGroup.html#overview">here</a>.
 */

public class Game {
   /**
    * the requested vector of all the 
    * star systems currently in play
    */ 
   public static Vector StarSystemVector=new Vector();

   /**
    * the requested vector of all the 
    * planets currently in play
    */

   public static Vector PlanetVector=new Vector();

   /**
    * the requested vector of all the
    * environs currently in play
    */
   public static Vector EnvironVector=new Vector();

   public int currentGalEvent;
   public static boolean done;
    public static boolean AfterMove=false;
   
   public int initialImperialForcePoints;
   public int currentImperialForcePoints;

   public int initialRebelForcePoints;
   public int currentRebelForcePoints;


   public int totalGameTurns;
   public int currentGameTurn;
    public static int GuiTurns=0;
    public static int First=0;

   static HumanPlayer humanPlayer = new HumanPlayer();
   /**
    * 1 = human 
    * 2 = ai
    */
   public int playerTurn;
   
   public int getPlayerTurn() {
      return playerTurn;
   }
   
   /**
    *getPhasingPlayer()
    *returns 0 if imperial, 1 if rebel, -1 if not phasing
    */
   public int getPhasingPlayer()
   {
      if(playerTurn==0)
          return -1;
      if(playerTurn%2==0)
          return 0;
      return 1;
   }

  /**
   * 0 = no winner
   * 1 = human, and other odd numbers
   * 2 = ai, and other even numbers greater than zero
   */
   public int winner;
   
   /**
    * gameType:
    *    's' = star system game
    *    'p' = province system game
    *    'g' = galactic game
    */
   public char gameType;

   /** 
    * scenario type:
    *    'a' = Armageddon
    *    'r' = start Rebellion
    */
   public char scenarioType;


   public Environ mexico; // for testing only
   public boolean searchPhase;
   public boolean operationsPhase;
   public boolean missionsPhase;
   public boolean interphase;
   public boolean instantVictory;
   protected int totalVictoryPoints;
   protected int currentVictoryPoints;


   public static boolean segments[] = new boolean[3];
   public static int NumPlayerTurns;



  /**
   * holds egrix, varu, name of 
   * saved game, etc
   */
   public String gameName;

   public Group imperialUnits;
   public Group rebelUnits;

   Vector imperialCharacter;
   Vector rebelCharacter;
   Vector imperialMilitia;
   Vector rebelMilitia;

  /**
   * test main, this function is unimportant
   */

   public static void main(String args[]){
      Game a = new Game("datfiles/egrix.dat");
}


/**
 * The methods below handle the game flow
 * Checks for stuff like victory points still needs to be added
 * May also add checks in for the 'DONE' button
*/
               
             
   public void PhaseChange()
      {  
        if(operationsPhase)
           {
              setSearchPhase();
           }
        else if(searchPhase)
           {
              setMissionPhase();
           }
        else if(missionsPhase)
           {
              if(playerTurn<NumPlayerTurns)
                 {
                    UpdatePlayerTurn();
                 }
              else
                 {
                    setInterphase();
                    showVictoryPoints();
                 }
            }
        else if(interphase)
           {
              showVictoryPoints();
              UpdateGameTurns();
              instantVictoryCheck();
           }
      }


   public void UpdateGameTurns()
      {
	  //if(First==0) Make.getStuff();
	  //         if(First==0) {Make2.getStuff2(); First++; while(!done);}
	  if(First==0) {Make2.getStuff2(); First++;}
          done=false;
          if(currentGameTurn < totalGameTurns)
                  {
                     currentGameTurn++;
		     fitg.start.dis.inGameTurn();
                     UpdatePlayerTurn();
                  }
               else
                  {
                     compareVictoryPoints();
                  }
                   
       }           
                   

  public static void setDone()
       {
               done = true;
       }

  public void UpdatePlayerTurn()
      {
               playerTurn++;
	       fitg.start.dis.resetPlayerTurn();
               setOperationsPhase();
      }
       
       
   private void setMissionPhase()
      {
         operationsPhase = false;       // Probably don't need all this extra code
         searchPhase = false;          // It's just there to avoid mulitple phases occurring at once
         missionsPhase = true;
         interphase =  false; 
	 fitg.start.dis.resetPhase();
	 done = false;
	 MissionCard.init();
	 MissionGroupAssign bob = new MissionGroupAssign();
         while(!done);    //Waits for missions phase to finish
	 done = false;
         PhaseChange();
      }

   private void setOperationsPhase()
      {
         operationsPhase = true;      // Probably don't need all this extra code
         searchPhase = false;          // It's just there to avoid mulitple phases occurring at once
         missionsPhase = false;
         interphase =  false;  
	 fitg.start.dis.resetPhase();
         setSegments(0);
         //insert call to first segment of operations phase
	 MvmtStarSystemgui.getMoveGui((StarSystem)StarSystemVector.elementAt(0));
	 done=false;
	 while(GuiTurns!=0 && !done);
	 System.out.println("Done with Move");
	 done=false;
	 AfterMove=true;
         setSegments(1);
	 //tauntWindow x = new tauntWindow();  // just put here for testing purposes
         //if(totalGameTurns%2==0) x.show();
	 //while(!done);
	 //insert call to second segment of operations phase
         setSegments(2);
         //insert call to third segment of operations phase
         PhaseChange();
      }
       
  private void setSearchPhase()
      {
         operationsPhase = false;      // Probably don't need all this extra code
         searchPhase = true;          // It's just there to avoid mulitple phases occurring at once
         missionsPhase = false;
         interphase =  false;  
         fitg.start.dis.resetPhase();
         setSegments(0);
	 done=false;
	if(EnvironVector.size()!=0){ 
	    ((Environ)EnvironVector.elementAt(0)).search(playerTurn,PlanetVector);
	    
	    while(GuiTurns!=0 && !done);
	}
         done = false;
         //insert call to first segment of search phase
         setSegments(1);
         //insert call to second segment of search phase
         setSegments(2);
         //insert call to third segment of search phase
         PhaseChange();
      }

  private void setInterphase()
      {
         operationsPhase = false;      // Probably don't need all this extra code
         searchPhase = false;          // It's just there to avoid mulitple phases occurring at once
         missionsPhase = false;
         interphase =  true;   
         playerTurn = 0;
         PhaseChange(); 
      }
       
  public void setSegments(int i)   // the main purpose for boolean flags is for the signs for the GUI to display certain info
     {
            segments[i % 3] = true;
            segments[(i+1) % 3] = false;
            segments[(i+2) % 3] = false;
     }
      
      
  /**
   * constructor for game class: takes name of file
   * from which to get data for game initialization
   * name of file must include appropriate suffix
   * for the time being, it ends the program if
   * the source file isn't found.  Maybe we'll get
   * around to changing that later.
   */

   public Game(String sourceFile){
      Galaxy.init();
      Charactr.init();
      Possession.init();
      Spaceship.init();

      initialImperialForcePoints=0;
      currentImperialForcePoints=0;
      initialRebelForcePoints=0;
      currentRebelForcePoints=0;
      currentGameTurn=0;
      currentVictoryPoints=0;
//      segment=0;
      playerTurn=0;
      winner=0;
      searchPhase=false;
      operationsPhase=false;
      missionsPhase=false;
      interphase=true;
      instantVictory=false;
      StarSystemVector = new Vector();
      PlanetVector = new Vector();
      EnvironVector = new Vector();
      imperialCharacter = new Vector();
      rebelCharacter = new Vector();
      imperialMilitia = new Vector();
      rebelMilitia = new Vector();
      NumPlayerTurns = 2;
      done = false;


      //HumanPlayer humanPlayer = new HumanPlayer();
      //  AI aiPlayer = new AI();
      try{
         BufferedReader data = new BufferedReader(new FileReader(sourceFile));
         String line = null;
         line = data.readLine();
         if( line == null ){
            System.out.println("Source file appears to be empty\b");
            System.out.println("Closing fitg");
            System.exit(0);
         }

         line.trim();
         while( line.equals("")) line = (data.readLine()).trim();
         while( line.charAt(0) == '#' ) line = (data.readLine()).trim();
         if(line.equals("scenario")){
            line = (data.readLine()).trim();
            // get game type from .dat file
            if( line.equals("StarGame"))           gameType = 's';
            else if( line.equals("ProvinceGame"))  gameType = 'p';
            else if( line.equals("GalaxyGame"))    gameType = 'g';
            // if .dat file is screwy, throw an exception and quit
            else throw new IOException();
            // get title of game from .dat file
            line = (data.readLine()).trim();
            gameName = line;
            // get goal of game from .dat file ie. start rebellion vs. armageddon
            line = (data.readLine()).trim();
            if( line.equals("Start Rebellion") )   scenarioType = 'r';
            if( line.equals("Armageddon"))         scenarioType = 'a';
            // total number of game turns in the game
            totalGameTurns = Integer.parseInt((data.readLine()).trim());
            // total number of victory points to win the game
            totalVictoryPoints = Integer.parseInt((data.readLine()).trim());
            // and finally this should read the '%' character
            line = (data.readLine()).trim();
         }

         while( line.charAt(0) == '#' ) line = (data.readLine()).trim();
         if(line.equals("stars")){
            line = (data.readLine()).trim();
            while( line.charAt(0) != '%' ){
	       StarSystemVector.addElement(StarSystem.getSystem(line));
               Planet temp[] = (StarSystem.getSystem(line)).getsystemplanets();
               for( int counter = 0; counter < temp.length; counter++ ){
                  PlanetVector.addElement( temp[counter]);
                  int innerc = (temp[counter]).getNumEnvirons();
                  Vector etemp = (temp[counter]).getEnvirons();
                  for( int blackAdder = 0; blackAdder < innerc; blackAdder++ ){
                     EnvironVector.addElement((Environ)etemp.elementAt(blackAdder));
                  }
               }
               line = (data.readLine()).trim();
            }
         }
         
         while( line.charAt(0) == '#' ) line = (data.readLine()).trim();
         Charactr tempcarray[] = Charactr.getCharInitArray();
         if(line.equals("characters")){
            boolean tempFlag;
            line = (data.readLine()).trim();
            while( line.charAt(0) != '%' ){
               if( line.charAt(0) == 'R' ) tempFlag = true;
               else                        tempFlag = false;
               line = line.substring(line.indexOf(",")+1, line.length()-1);
               for( int bob = 0; bob < tempcarray.length; bob++ )
                 if( line.equals( (tempcarray[bob]).getCharName() ) ){
                   if( tempFlag )
                     rebelCharacter.addElement(tempcarray[bob]);
                   else
                     imperialCharacter.addElement(tempcarray[bob]);
                 }
               line = (data.readLine()).trim();
            }
         }

         while( line.equals("")) line = (data.readLine()).trim();
         while( line.charAt(0) == '#' ) line = (data.readLine()).trim();
         if(line.equals("planets")){
            line = (data.readLine()).trim();
            while( line.charAt(0) != '%' ){
             // initialize all our happy planets appropriately
               // get a pointer to our planet, find the one mentioned
               // in the .dat file
               Planet temp = (Planet.get(line.substring(0, line.indexOf(","))));
               if( temp == null ) throw new IOException();
               // move on to the pbd level
               line = line.substring(line.indexOf(",")+1);
               temp.setPDBLevel( Integer.parseInt(line.substring(0,1) ) );
               // set pdb up or down
               line = line.substring(line.indexOf(",")+1);
               temp.setisPDBUp( line.charAt(0) == 'U' );  
               // get the state of the planet
               line = line.substring(line.indexOf(",")+1);
               if( line.indexOf("RebellionStopped") != -1 ){
                  temp.setRebellionState(2);
                  temp.setPlanetControl(3);
               }
               else if( line.indexOf("Rebellion") != -1 ){
                  temp.setRebellionState(1);
                  temp.setPlanetControl(2);
               }
               else if( line.indexOf("Rebel") != -1 ){
                  temp.setRebellionState(0);
                  temp.setPlanetControl(1);
               }
               else{
                  temp.setRebellionState(0);
                  temp.setPlanetControl(0);
               }
               // now set the actual control of the planet
               line = line.substring(line.indexOf(",")+1);
               if( line.charAt(0) == 'I' ) temp.setActualControl(0);
               else if( line.charAt(0) == 'R' ) temp.setActualControl(2);
               else temp.setActualControl(1);
               // finally set up the loyalty level!
               line = line.substring(line.indexOf(",")+1, line.length()-1);
               temp.setLoyalty(Integer.parseInt(line));
               
               // now read the next line of data
               line = (data.readLine()).trim();
            }
         }

         while( line.charAt(0) == '#' ) line = (data.readLine()).trim();
         if(line.equals("units")){
            line = (data.readLine()).trim();
            while( line.charAt(0) != '%' ){
	     // create all our militia units

               // add imperial units
               if( line.charAt(0) == 'I' ){
                  line = line.toLowerCase();
                  char vex = line.charAt(0);
                  line = line.substring(line.indexOf(",")+1);
                  String namo = line.substring(0, line.indexOf(","));
                  line = line.substring(line.indexOf(",")+1);
                  int comrat = Integer.parseInt(line.substring(0, line.indexOf(",")));
                  line = line.substring(line.indexOf(",")+1);
                  int scomrat = Integer.parseInt(line.substring(0, line.indexOf(",")));
                  imperialMilitia.addElement(new MilitaryUnit(vex, namo, comrat, 
                                             scomrat, null, true)  );
               }

               // add rebel units
               else{
                  line = line.toLowerCase();
                  char vex = line.charAt(0);
                  line = line.substring(line.indexOf(",")+1);
                  String namo = line.substring(0, line.indexOf(","));
                  line = line.substring(line.indexOf(",")+1);
                  int comrat = Integer.parseInt(line.substring(0, line.indexOf(",")));
                  line = line.substring(line.indexOf(",")+1);
                  int scomrat = Integer.parseInt(line.substring(0, line.indexOf(",")));
                  rebelMilitia.addElement( new MilitaryUnit( vex, namo, comrat, 
                                           scomrat, null, true) );
               }

               line = (data.readLine()).trim();
            }
         }

       
         while( line.charAt(0) == '#' )  line = (data.readLine()).trim();
         if(line.equals("possessions")){
            line = (data.readLine()).trim();
            while( line.charAt(0) != '%' ){
	     // finally create our possessions & hand 'em out
               if( line.charAt(0) == 'I' ){
                  line = line.substring(line.indexOf(",") +1);
                  String targetChar = line.substring(0, line.indexOf(","));
                  Charactr[] x = Charactr.getCharInitArray();
                  for( int billygoat =0; billygoat < x.length; billygoat++)                  
                     if( targetChar.equals((x[billygoat]).getCharName() )){
                        line = line.substring(line.indexOf(",")+1);
                        if( line.charAt(0) == 'S' ){
                           line = line.substring(line.indexOf(",")+1, line.length()-1);
                           Spaceship[] s = Spaceship.getSpaceshipInitArray();
                           for( int jackalope = 0; jackalope < s.length; jackalope++){
                              if(s[jackalope].getName() == line )
                                 x[billygoat].setIsPilot(true, s[jackalope]);
                           }

                        }
                        else{
                           line = line.substring(line.indexOf(",")+1);
                           line = line.substring(0, line.length() -1 );
                           Possession p = Possession.draw(line);
                           if( p != null )
                              (x[billygoat]).addPossession(p);
                        }
                     }
               }
               else{
                  line = line.substring(line.indexOf(",")+1);
                  String targetChar = line.substring(0, line.indexOf(","));
                  Charactr[] x = Charactr.getCharInitArray();
                  for( int fleacollar = 0; fleacollar < x.length; fleacollar++)
                    if( targetChar.equals((x[fleacollar]).getCharName())){
                        line = line.substring(line.indexOf(",")+1);
                        if( line.charAt(0) == 'S' ){
                           line = line.substring(line.indexOf(",")+1, line.length()-1);
                           Spaceship[] s = Spaceship.getSpaceshipInitArray();
                           for( int evilpuppy = 0; evilpuppy < s.length; evilpuppy++){
                              if( s[evilpuppy].getName() == line )
                                 x[fleacollar].setIsPilot(true, s[evilpuppy]);
                           }
                        }
                        else{
                           line = line.substring(line.indexOf(",")+1);
                           line = line.substring(0, line.length()-1);
                           Possession p = Possession.draw(line);
                           if( p != null )
                              (x[fleacollar]).addPossession(p);
                       }
                    }
               }
               line = (data.readLine()).trim();
            }
         }
        
         data.close();
      }
      catch(FileNotFoundException e ){
         System.out.println("The file wasn't found and may not exist!\n" +
               " Please make sure the .dat files are in the same\n" + 
               " directory as everything else!\n");
         System.out.println("Closing fitg");
         System.exit(0);
      }
      catch(IOException e){
         System.out.println("Error reading from source file\b");
         System.out.println("Closing fitg");
         System.exit(0);
      }

// this part hard coded to stick people in environs
// SPECIFIC TO EGRIX
// comment these lines out for any other purpose!!
      
      System.out.println("Test case: characters hardcoded into environs");
      mexico = Environ.get(2231);
      Charactr[] folks = Charactr.getCharInitArray();
      for( int blob =0; blob < folks.length; blob++ ){
	if(    ( (folks[blob].getCharName()).indexOf("Boca") != -1 ) ||
               ( (folks[blob].getCharName()).indexOf("Sont") != -1 ) ||
               ( (folks[blob].getCharName()).indexOf("Frun") != -1 ) ||
               ( (folks[blob].getCharName()).indexOf("Vans") != -1 ) ||
               ( (folks[blob].getCharName()).indexOf("Kidu") != -1 ) 
            )
             ;
        mexico.addCharacter(folks[blob]);
	
      }
     
  MilitaryUnit un=new MilitaryUnit('r',"Veteran",5,4,mexico,true);
      mexico.getRebelMilGroup().add(un);
      MilitaryUnit unit=new MilitaryUnit('r',"Veteran",5,4,mexico,true);
      mexico.getRebelMilGroup().add(unit);

      Spaceship.init();
      Spaceship[] spaceships = Spaceship.getSpaceshipInitArray();
      Spaceship slo= spaceships[4];
      slo.setEnviron(mexico);
      addPlanet(Planet.get("Charkhan"));
      addEnviron(mexico);

      PlanetVector = new Vector();


      PlanetVector.add(Planet.get(  221  ));
      PlanetVector.add(Planet.get(  222  ));
      PlanetVector.add(Planet.get(  223  ));      

      System.out.println("planets added: " + PlanetVector.size() );

      StarSystemVector = new Vector();
      StarSystemVector.add(StarSystem.get( 22 ));

      EnvironVector = new Vector();

      EnvironVector.add( Environ.get(2211)  );
      EnvironVector.add( Environ.get(2221)  );
      EnvironVector.add( Environ.get(2231)  );
      EnvironVector.add( Environ.get(2232) );


   }

   public void updatePhase(){
      ;
   }


   // returns actual winner and calls applet 
   // 0-no winner, 1-imperial, 2-rebel
   public void WhoWon( int win )
   {
      if(win == 1){
         JOptionPane.showMessageDialog( null, "IMPERIAL WINS!!!", "Who Won", JOptionPane.INFORMATION_MESSAGE );
      }
      else if(win == 0){
         JOptionPane.showMessageDialog( null, "THERE ARE NO WINNER!", "Who Won", JOptionPane.INFORMATION_MESSAGE );
      }
      else{ 
         JOptionPane.showMessageDialog( null, "YOU WIN!", "Who Won", JOptionPane.INFORMATION_MESSAGE );
      }

      //System.exit( 0 );
   }

   // compares victory points to see who wins
   public void compareVictoryPoints()
   {
      currentVictoryPoints = humanPlayer.calcPoints(0);
      if(currentVictoryPoints >= totalVictoryPoints){
         WhoWon(2); // rebel wins 
      }
      else {
         WhoWon(1); // imperial wins 
      }
   }

   public void instantVictoryCheck()
   {
      System.out.println("Error. Method incomplete.");
      /* 
       *  checks if instant victory is possible
       *  1.  Star System Game and Rebellion Scenario
       *      Rebel wins if any planet is ever Rebel-controlled
       *      Imperial wins if all Rebel characters are killed or captured
       *      and all planets are imperial-controlled
       *  2.  Star System Game and Armageddon Scenario
       *      Rebel wins if Cercis and one other planet are both Rebel
       *      cotrolled
       *      Imperial wins if all three planets are Imperial-controlled and
       *      at least three Rebel characters are killed or captured
       *  3.  Province Game and Rebellion Scenario
       *      Rebel wins if Orning, Cieson, and any other one planet are
       *      Rebel-controlled
       *      Imperial wins if at any time after Game Turn two, there are 
       *      no planets that are Rebel-controlled or in rebellion and
       *      there are no rebel military units in play
       *  4.  Province Game and Armegeddon Scenario
       *      Rebel wins if Diomas(152) and Orlog(162) are Rebel-controlled 
       *      the end of any Game Turn
       */

   }

   public void showVictoryPoints()
   {
      String output;
      output = humanPlayer.toString();            
      JOptionPane.showMessageDialog( null, output, "Showing Victory Points", JOptionPane.INFORMATION_MESSAGE );
 
   }


   
   public void MissionTestPlayerTurnEquals1()
   {
       playerTurn=1;
   }
 
   public static void addPlanet(Planet p)
    { 
	PlanetVector.add(p);
    } 


   public static void addEnviron(Environ e)
   {
      EnvironVector.add(e);
   }

   public static void setNumGui()
    {
	GuiTurns++;
    }

    public static void desetNumGui()
    {
	GuiTurns--;
    }

    public static void printNumGui()
    {
	System.out.println("GuiTurns is:"+GuiTurns);
    }

    public static int getNumGui()
    {
	return GuiTurns;
    }
    public static boolean getAfterMove()
    {
    return AfterMove;
    }
    public static void setBeforeMove()
    {
    AfterMove=false;
    }

}
