/**
 * @file Game.java
 *
 * @author
 *    Christos Choutouridis
 *    <cchoutou@ece.auth.gr>
 *    AEM:8997
 */

/** 
 * @mainpage A labyrinth board game
 *
 * @section intro_sec Introduction
 *
 * This is the introduction.
 *
 * etc...
 */
package host.labyrinth;

import java.util.Scanner;

/**
 * Main application class. This class is the only public interface of
 * the entire game.
 */
public class Game {

   /**< An empty constructor */
   Game() {
      scan = new Scanner(System.in);
   }

   /** @name Player main application interface */
   /** @{ */
   /** Utility to get current round of the game */
   int round ()      { return round; }
   /** Utility to increase and get the increased round of the game */
   int nextRound()   { return ++round; }

   /**
    * Utility to hold the execution of the program waiting for user input.
    * This is true only if the user passed the interactive flag.
    */
   void waitUser () {
      if(Session.interactive) {
         System.out.println("Press enter to continue...");
         scan.nextLine();
      }
   }
   /** @{ */

   /**
    * @name Accessor/Mutator interface
    * @note
    *    Please consider not to use mutator interface. Its the abstraction killer :(
    *    We have added a bit of logic however, in order to make it a bit more safe.
    */
   /** @{ */
   int getRound()             { return round; }
   void setRound (int round)  { this.round = round; }
   /** @} */

   /** @name Game's data */
   /** @{ */
   private int round;      /**< Holds the round of the game */
   private Scanner scan;   /**< Input handle used in interactive mode */
   /** @} */

   /**
    * Command line argument handler
    */
   static boolean getArguments (String[] args) {
      for (int i =0 ; i<args.length ; ++i) {
         switch (args[i]) {
            case "-b":
            case "--board":
               if (i+1 < args.length)
                  Session.boardSize = Integer.parseInt(args[++i]);
               break;

            case "-s":
            case "--suplies":
               if (i+1 < args.length)
                  Session.supplySize = Integer.parseInt(args[++i]);
               break;

            case "-r":
            case "--rounds":
               if (i+1 < args.length)
                  Session.maxRounds = Integer.parseInt(args[++i]);
               break;

            case "--norooms":
               Session.loopGuard = true;
               break;

            case "-i":
            case "--interactive":
               Session.interactive = true;
               break;

            default:
            case "-h":
            case "--help":
               System.out.println("Labyrinth Game");
               System.out.println("");
               System.out.println("Usage:");
               System.out.println("labyrinth [-b|--board <Num>] [-s|--supplies <Num>] [-r|--rounds <Num>] [--norooms] [-i|--interactive]");
               System.out.println("or");
               System.out.println("labyrinth -h|--help");
               System.out.println("\nOptions\n");
               System.out.println("-b  | --board:\n   Sets the size of board's edge.\n");
               System.out.println("-s  | --supplies:\n   Sets the number of supplies on the board.\n");
               System.out.println("-r  | --rounds:\n   Sets the maximum number of rounds of the game.\n");
               System.out.println("--norooms:\n   Prevents the creation of closed rooms inside the board.\n");
               System.out.println("-i  | --interactive:\n   Each round requires user input in order to continue.\n");
               System.out.println("-h  | --help:\n   Print this and exits.");
               return false;
         }
      }
      return true;
   }


   /**
    * Main game loop
    */
   public static void main(String[] args) {
      try {
         // Get command line options
         if (!Game.getArguments(args)) throw new Exception("");

         // Create a game, a board and 2 players.
         Game game   = new Game();
         Board board = new Board(Session.boardSize, Session.supplySize);
         Player T    = new Player(1, "Theseus", true, board, 0);
         Player M    = new Player(2, "Minotaur", false, board, Position.toID(Session.boardSize/2, Session.boardSize/2));

         // Populate data to the board
         board.createBoard(T.playerTileId(), M.playerTileId());

         // Initial board printout
         System.out.println("Initial board: " + (game.round()));
         board.printBoard(
               board.getStringRepresentation(T.playerTileId(), M.playerTileId())
         );
         game.waitUser ();
         // Main game loop
         while (true) {
            int[] m;
            System.out.println();
            System.out.println("State after round: " + (game.round()+1));

            // Player moves
            m = T.move(T.playerTileId());
               System.out.println(T.getName() + ":\t tileId =" + m[0] + " (" + m[1] + ", " + m[2] + ")");
            m = M.move(M.playerTileId());
               System.out.println(M.getName() + ":\t tileId =" + m[0] + " (" + m[1] + ", " + m[2] + ")");
            board.printBoard(
                  board.getStringRepresentation(T.playerTileId(), M.playerTileId())
            );

            // Loop termination cases
            if (T.getScore() == 4) {
               System.out.println(T.getName() + " Wins!!! Score =" + T.getScore());
               System.exit(0);
            }
            if (M.getScore() == 4 || M.playerTileId() == T.playerTileId()) {
               System.out.println(M.getName() + " Wins!!! Score =" + M.getScore());
               System.exit(0);
            }
            if (!(game.nextRound() < Session.maxRounds)) {
               System.out.println("New day has come... Tie!!!");
               System.exit(0);
            }
            game.waitUser ();
         }
      }
      catch (Exception e) {
         // We don't handle exceptions. Print error and exit with error status.
         System.out.println(e.getMessage());
         System.exit(1);
      }
   }
}
