-----------------------------------------------------------------------------
-- |
-- Module      :  Control.Concurrent.STM.TSkipList
-- Copyright   :  Peter Robinson 2014
-- License     :  LGPL
-- 
-- Maintainer  :  Peter Robinson <thaldyron@gmail.com>
-- Stability   :  experimental
-- Portability :  portable
-----------------------------------------------------------------------------
module Main
where
import Board
import Strategy

import Control.Monad
import Control.Monad.Random
import Control.Monad.State
import Data.Char
import System.IO.Unsafe
import Data.List((!!))
import Control.Applicative((<$>))

main = do
  let board = emptyBoard 4
  putStrLn "Use a,d,w,s to swipe."
  runSimulation True allHuman (emptyBoard 4)
  return ()

data GameState = GameState
  { board      :: Board
  , output     :: Bool
  , moveNumber :: Int
  }
  deriving (Show)

--newtype GameMonad = GameMonad
--  { runGame :: StateT IO a }

            
simulateMany :: Int -> Bool -> Strategy -> Int -> IO ()
simulateMany n output strat bs = do
  let initialBoard = emptyBoard bs
  maxvals <- sequence $ replicate n $ 
                maxValue <$> runSimulation output strat initialBoard
  putStrLn $ "Average max value: " ++ show ((sum maxvals) `div` n)

runSimulation :: Bool -> Strategy -> Board -> IO Board
runSimulation output strat board = do
  simulate output strat 1 board
  where
  simulate output strat i board = do
    let ecoords = emptyCells board 
    randIx <- getRandomR (0,length ecoords-1) 
    randValue <- getRandomR (1,2) 
    if ecoords == [] then do
        when output $ gameOver output i board >> return ()
        return board
      else do
        let newBoard = setValue (ecoords!!randIx) (2*randValue) board
        getMove newBoard
        where
        getMove newBoard = do      
          when output $ do {
            putStrLn $ "Moves played: " ++ show i;
            putStrLn $ prettyPrint newBoard }
          dir <- runStrategy strat newBoard >>= 
                 maybe getInput return 
          print dir
          if not $ isPossible dir newBoard
            then do
              if and [ not $ isPossible dir newBoard | dir <- [UP,DOWN,LEFT,RIGHT]]
                then gameOver output i newBoard
                else do
                  putStrLn "Can't move in this direction, try again!"
                  getMove newBoard
            else simulate output strat (i+1) $ swipe dir newBoard 


        gameOver output i board = do
          when output $ do
            putStrLn $ "Hmm..." ++ show (i-1) ++ 
                       " moves!?\nAnd your maximum tile value is " 
                       ++ show (maxValue board) ++ ". Not so bad, ah? :)"
            putStrLn $ prettyPrint board
          return board

getInput :: IO Direction
getInput = do
      o <- getChar
      putStrLn ""
      maybe (do putStrLn "Use a,d,w,s to swipe."
                getInput)
            (\o -> return o)
            (case toLower o of {
                'a' -> Just LEFT ;
                'd' -> Just RIGHT ;
                'w' -> Just UP ;
                's' -> Just DOWN ;
                 _  -> Nothing })
