--- Tic-tac-toe is a paper-and-pencil game for two players who take turns marking the spaces
--- in a three-by-three grid with X or O.
--- The player who succeeds in placing three of their marks in a horizontal, vertical, or
--- diagonal row is the winner. It is a solved game, with a forced draw assuming best play from both players.
--- The module Logic.Game contains the game logic.
module CLI.TicTacToe;

import Stdlib.Prelude open;
import Logic.Game open;

--- A ;String; that prompts the user for their input
prompt (state : GameState) : String :=
  "\n"
    ++str showGameState state
    ++str "\nPlayer "
    ++str showSymbol (GameState.player state)
    ++str ": ";

nextMove (state : GameState) (string : String) : GameState :=
  string |> stringToNat |> validMove |> flip playMove state;

--- Main loop
terminating
run (state : GameState) : IO :=
  case GameState.error state of
    | terminate msg :=
      printStringLn
        ("\n"
          ++str showGameState state@GameState{error := noError}
          ++str "\n"
          ++str msg)
    | continue msg :=
      let
        state' := state@GameState{error := noError};
      in printString (msg ++str prompt state')
        >>> readLn (nextMove state' >> run)
    | _ := printString (prompt state) >>> readLn (nextMove state >> run);

--- The welcome message
welcome : String :=
  "MiniTicTacToe\n-------------\n\nType a number then ENTER to make a move";

--- The entry point of the program
main : IO := printStringLn welcome >>> run beginState;