/*------------------------------------------------------------------------------
Projekt: ICP - game Othello
Authors: Michal Schorm (xschor02)
Date: FIT VUTBR 2016                                                

File content: class Board
-------------------------------------------------------------------------------*/
#include "./Board.cpp"  // game must have game Board
#include "./Player.cpp" // and some players of course

using namespace std;



//!  Class Game - represents Game object, consists from Board and Players.
/*!
Provide aditional info about match.
Counts turns made.
Contain methods to play
*/
#ifndef GAME_CLASS_FULL
#define GAME_CLASS_FULL
class Game
{
 private:
   //! pointer to game Board 
   Board * board;
   //! counter of turns played
   int roundCounter = 0;
   //! pointer to the black player (he starts the match)
   Player * playerBlack;
   //! pointer to white player
   Player * playerWhite;
   
   
   
 public:
   //! Constructor create game Board and place 4 disks in the middle (game rules)
   Game()
     {
      int size = this->setGameSize();
      this->board = new Board(size);
      
      this->setPlayer(white);
      this->setPlayer(black);
      
      // first four disks placed
      this->board->getField((size/2)  , (size/2)  )->putDisk(new Disk(white));
      this->board->getField((size/2)+1, (size/2)+1)->putDisk(new Disk(white));
      this->board->getField((size/2)  , (size/2)+1)->putDisk(new Disk(black));
      this->board->getField((size/2)+1, (size/2)  )->putDisk(new Disk(black));   
     }

   //! get desired size of game Board from teh user via console
   int setGameSize()
     {
      int boardSize;
      do{
         cout << "Zadejte velikost hracího pole [6, 8, 10, 12]: ";
         cin >> boardSize;
        } while(boardSize != 6 &&  boardSize != 8 &&  boardSize != 10 &&  boardSize != 12);
      return boardSize;
     }

   //! get player name (or AI names) for color given
   void setPlayer(DiskColor color)
     {
      string playerName; 
      
      do{
         cout << "Přidejte hráče ";
         if(color == white) cout << "WHITE (1)";
         else if(color == black) cout << "BLACK (2)";
         cout << ". Buďto zadejte jméno [3-20 znaků] nebo vyberte UI [ ";
         Player::writePlayers();
         cout << " ]: ";
         cin >> playerName;        
        
         if( playerName.size()<20 && playerName.size()>3 ) break;
         cout << "Chybně zadané jméno hráče, zkuste to znovu\n";
        } while(1);
        
      if(color == white) this->playerWhite = new Player(playerName, white);
      else if(color == black) this->playerBlack = new Player(playerName, black);     
     }  


   //! call Board method to draw board into the console
   void drawGame()
     {
      this->board->drawBoard();
     }   

   //! write out number of game round given
   void drawGameRound(int gameRound)
     {
      cout << "Tah číslo: " << (this->roundCounter)+1 << "\n";
     } 

   //! write out stats of game round given
   void drawStats(int gameRound)
     {
      cout << "Hráč " << this->playerWhite->getName() << " (1) má " << this->board->amount(white) << " kamenů. Hráč " << this->playerBlack->getName() << " (2) má "  << this->board->amount(black) << " kamenů.\n";
     } 
  
   //! write our which player is n the turn at game round given    
   void drawPlayerOnTurn(int gameRound)
     {
      if(((this->roundCounter)%2)==0) cout << "Na řadě je hráč: " << this->playerBlack->getName() << " (2)\n"; else cout << "Na řadě je hráč: " << this->playerWhite->getName() << " (1)\n";
     }   

   //! returns pointer to game Board
   Board * getBoard()
     {
      return this->board;
     }   

   //! returns actual game round
   int getGameRound()
     {
      return this->roundCounter;
     }  

   //! returns (true/false) if current player can put his disk on coordinates given
   bool canPlayMove(int x, int y)
     {
      //cout << "canPlayMove(" << x << "," << y << ")\n";  // CLI debugg output
      DiskColor color;
      if(((this->roundCounter)%2)==0) color=black;
      else color=white;
      bool output = this->board->getField(x, y)->canPutDisk(color);
      return output;
     } 

   //! returns (true/false) if current player can put his disk on coordinates given AND put disk onto that position
   bool playMove(int x, int y)
     {
      if( this->canPlayMove(x, y) )
        {
         DiskColor color;
         if((((this->roundCounter)++)%2)==0) color=black;
         else color=white;
         this->board->getField(x, y)->putDisk(new Disk(color));
         return true;
        }
      return false;  
     } 

   //! To the end of the match calls Players to make their turns and provide some adidtional info to console.  
   void play()
     {
      Player * player;
      
      while(1)
        {
         system("clear");
         this->drawGame();
         
         if( this->board->checkWin() != none ) break;
         if( !(this->board->checkCanPlay(white)) && !(this->board->checkCanPlay(black) ) )
           {
            cout << "Žádný hráč už nemůže hrát";
            break;
           }
         
         
         this->drawGameRound(roundCounter);
         this->drawStats(roundCounter);
         this->drawPlayerOnTurn(roundCounter);
         
         if((((this->roundCounter)++)%2)==0) player=this->playerBlack;
         else player=this->playerWhite;            
         //if( board->checkCanPlay(player->getColor()) ){ cout << "Hráč " << player->getColor() << " může provést tah. Čeká se na jeho tah.\n"; }
         //else{ cout << "Hráč " << player->getColor() << " NEmůže provést tah. Jeho tah se přeskakuje.\n\n"; continue;}         
         if( !( board->checkCanPlay(player->getColor()) ) ) continue;

         player->play(this->board);
         cout << endl;
        }
      
      cout << "\nKonec hry.\n";
      this->drawStats(roundCounter);
       
     }
            
};

#endif