// 1. Lastenheft
// 2. Pflichtenheft
//
// Einschraenkungen:
// 0. 3x3 Spielfeld
// 1. Player sind dynamisch
// 2. Einfaches Kommandozeilen-Interface 
//    _ für frei, O für weiß, X für schwarz
//    Eingabe: 1-9 -> Zellen 
// 3. Computer ist ganz dumm - erste freie Feld

#include <iostream>
#include <limits>
#include "board.h"
#include "computerrnd.h"
#include "computerff.h"
#include "computerlf.h"
#include "human.h"
#include "move.h"
using namespace std;

PlayerPtr definePlayer(int no, Color color)
{
   for (;;)
   {
      cout << "Wer soll der " << no << ". Spieler sein:\n";
      cout << "- 1 : Mensch\n";
      cout << "- 2 : Computer-FF\n";
      cout << "- 3 : Computer-LF\n";
      cout << "- 4 : Computer-Rnd\n";

      int input;
      cin >> input;
      if (cin.fail())
      {
         cout << "- Bitte Zahl eingeben\n\n";
         cin.clear();
         cin.ignore(numeric_limits<streamsize>::max(), '\n');
         continue;
      }

      switch (input)
      {
      case 1:
         return make_unique<Human>(color);
      case 2:
         return make_unique<ComputerFF>(color);
      case 3:
         return make_unique<ComputerLF>(color);
      case 4:
         return make_unique<ComputerRnd>(color);
      }
      cout << "- Bitte Zahl zwischen 1 und 4 eingeben\n\n";
   }
}

enum class PlayReturnType { GoOn, Stop };

PlayReturnType play(Player& pl, Board& board)
{
   // 2. Der Spieler wird nach seinem Zug gefragt
   //    Zug ausgibt
   Move move = pl.askForMove(board);
   cout << pl.getName() << ": ";
   move.print();

   // 3. Zug gemacht werden
   //    Spielbrett ausgeben
   board.set(move);
   board.print();

   // 4. Hat der Spieler gewonnen?
   //    Ja => Gratulation, Ende des Spiels
   //    Nein => Weiter
   if (board.hasWin(move.getColor()))
   {
      cout << "\nGratulation\n" << pl.getName() << " hat gewonnen\n\n";
      return PlayReturnType::Stop;
   }

   // 5. Ist remis ausgegangen
   //    Ja => Remis-Ausgabe, Ende des Spiels
   //    Nein => Weiter
   if (board.isRemis())
   {
      cout << "\nRemis\n\n";
      return PlayReturnType::Stop;
   }

   return PlayReturnType::GoOn;
}

int main()
{
   cout << "Tic-Tac-Toe 2\n\n";

   // 0. Spieler anlegen
   PlayerPtr pl1 = definePlayer(1, Color::white);
   PlayerPtr pl2 = definePlayer(2, Color::black);

   // 1. Spielbrett + Ausgabe
   Board board;
   board.print();

   for (;;)
   {
      if (play(*pl1, board) == PlayReturnType::Stop) break;
      if (play(*pl2, board) == PlayReturnType::Stop) break;
   }
}
