module Main where

import Data.Maybe
import System.Environment
import System.IO
import Text.Read

import Node(Node(..))
import qualified Node
import qualified Puzzle
import qualified Search
import qualified Animation

main::IO ()
main = getInputPuzzle >>= \maybePuzzle -> getArgs >>= \argv ->
  case maybePuzzle of
    Nothing -> putStrLn "Invalid puzzle input." >> main
    Just puzzle -> if Puzzle.isValidState puzzle
                   then Search.solvePuzzleThreaded puzzle >>= display argv
                   else putStrLn "Unsolvable puzzle entered."
  where display argv = if "-cli" `elem` argv
                       then printSolution
                       else Animation.animateSolution

-- | Returns the 3x3 board based on user input,
-- or IO Nothing in the case of invalid input.
getInputPuzzle::IO (Maybe [[Int]])
getInputPuzzle = getPuzzleRec []
  where getPuzzleRec puzzle@[_, _, _] = return $ Just puzzle
        getPuzzleRec puzzle = putStr "Row>> " >> hFlush stdout >>
                              getLine >>= \input ->
          let row = mapMaybe readMaybe $ words input ::[Int]
          in if length row /= 3
             then return Nothing
             else getPuzzleRec (puzzle ++ [row])

-- | Displays the calculated set of moves given a solution node.
printSolution::Node -- ^ The solution node.
             -> IO ()
printSolution node = mapM_ print nodes >> putStrLn ("Moves: " ++ show (length nodes - 1))
  where nodes = Node.toList node
