
import Control.Monad.Random

data GameState = GameState
    { _field             :: Field
    , _fieldWidth        :: Int
    , _fieldHeight       :: Int
    , _combo             :: Int
    , _points            :: Int
    , _gameRound         :: Int
    , _thisPieceType     :: Block
    , _nextPieceType     :: Block
    , _thisPiecePosition :: (Int, Int)
    }


mkGameState :: Int -> Int -> GameState
mkGameState width height = GameState
    { _field             = [[]]
    , _fieldWidth        = width
    , _fieldHeight       = height
    , _combo             = 0
    , _points            = 0
    , _gameRound         = 0
    , _thisPieceType     = I
    , _nextPieceType     = Z
    , _thisPiecePosition = (5, -1)
    }


newtype GameContext a = GameContext { runGameContext :: RandT StdGen (StateT GameState IO) a }
    deriving (Functor, Applicative, Monad, MonadIO, MonadRandom, MonadState GameState)


class (Functor m, Applicative m, Monad m, MonadIO m) => MonadGame m where
    liftGame :: GameContext a -> m a


runGame :: GameContext () -> IO ()
runGame action = do
    g <- newStdGen
    let context = mkGameState 20 15
    runStateT (runRandT (runGameContext (initGame >> action)) g) context
    return ()
  where
    initGame = do
        this <- getRandom
        next <- getRandom
        modify $ \st -> st
            { _thisPieceType = this
            , _nextPieceType = next
            }

