module Text.HPaco.Readers.Paco
    ( readPaco
    , readCapo
    )
where

import Control.Monad
import Control.Monad.IO.Class
import Text.HPaco.Reader
import Text.HPaco.Readers.Paco.ParserInternals
import Text.HPaco.Readers.Paco.Basics
import Text.HPaco.Readers.Paco.Statements as PacoStatements
import Text.HPaco.Readers.Capo.Statements as CapoStatements
import Text.HPaco.AST.AST
import Text.HPaco.AST.Statement
import Text.HPaco.AST.Expression
import Control.Exception (throw)
import System.IO (withFile, IOMode (ReadMode))
import System.IO.Strict
import System.FilePath

readPaco = readRaw pacoDocument
readCapo = readRaw capoDocument

readRawAuto parser filename =
    case (takeExtension filename) of
        ".capo" -> readCapo filename
        ".paco" -> readPaco filename
        otherwise -> readRaw parser filename

readRaw :: Parser AST -> Reader
readRaw parser filename =
    let pstate = defaultPacoState
                    { psBasePath = takeDirectory filename
                    , psIncludeExtension = renull $ takeExtension filename
                    , psHandleInclude = readRawAuto parser
                    }
    in readRawWithState parser pstate filename
    where renull "" = Nothing
          renull x = Just x

readRawWithState :: Parser AST -> PacoState -> Reader
readRawWithState parser pstate filename src = do
    result <- runParserT parser pstate filename src
    either
        throw
        return
        result

pacoDocument = document PacoStatements.statements
capoDocument = document CapoStatements.statements

document :: Parser [Statement] -> Parser AST
document pstatements = do
    stmts <- pstatements
    eof
    pstate <- getState
    return $ AST 
                { astRootStatement = StatementSequence stmts
                , astDefs = psDefs pstate
                , astDeps = psDeps pstate
                }