module Repl (repl) where

import Paths_mappy
import System.Console.ANSI
import System.Console.Haskeline
import System.Directory
import Text.ParserCombinators.Parsec
import Data.List (intercalate)

import Mappy
import Language.Ast
import Language.Desugar
import Language.Error
import Language.Error.PrettyPrinter()
import Language.Executor
import Language.Parser

preludePath :: IO FilePath
preludePath = getDataFileName "prelude.map"

mappyAsciiArt :: String
mappyAsciiArt =
  '\n':intercalate "\n" [
      "|  \\/  |                        "
    , "| .  . | __ _ _ __  _ __  _   _ "
    , "| |\\/| |/ _` | '_ \\| '_ \\| | | |"
    , "| |  | | (_| | |_) | |_) | |_| |"
    , "\\_|  |_/\\__,_| .__/| .__/ \\__, |"
    , "             | |   | |     __/ |"
    , "             |_|   |_|    |___/ "]

repl :: IO ()
repl = do
  prelude <- preludePath >>= readMappyFile
  setSGR [SetColor Foreground Vivid Green]
  putStrLn mappyAsciiArt
  setSGR [Reset]
  home <- getHomeDirectory
  repl' (fst <$> validatePreExec prelude, concat [home, "/", ".mappy_history"])

repl' :: (Either [Error Expression] Env, FilePath) -> IO ()
repl' (Left errors, _) = putStrLn $ show errors
repl' (Right initialEnv, histFile) = runInputT settings (go initialEnv)
  where
  settings = defaultSettings { historyFile = Just histFile }
  go env = do
    line <- getInputLine "m> "
    case line of
      Nothing -> go env
      Just line' -> case parse defOrExpr "(unknown)" line' of
        Left err -> (outputStrLn $ show err) >> go env
        Right (Just (Left def)) ->
          let
            (MappyDef name value) = desugarEachDef def
          in
            go ((name, value):env)

        Right (Just (Right expr)) -> case eval env $ desugarExpr expr of
          v -> (outputStrLn $ print' v) *> go env

        Right Nothing -> go env