content: import GF.Compile
  import GF.Compile.Rename (renameSourceTerm)
  import GF.Compile.Concrete.Compute (computeConcrete)
  import GF.Compile.Concrete.TypeCheck (inferLType)
  import GF.Data.Operations
  import GF.Grammar
  import GF.Grammar.Parser
  import GF.Infra.Option
  import GF.Infra.UseIO
  import GF.Infra.Modules (greatestResource)
  import GF.Infra.CheckM
  import GF.Text.UTF8
  
  import Network.FastCGI
  import Text.JSON
  import Text.PrettyPrint
  import qualified Codec.Binary.UTF8.String as UTF8 (decodeString, encodeString)
  import Data.ByteString.Char8 as BS
  
  import Control.Monad
  import System.Environment
  import System.FilePath
  
  import Cache
  import FastCGIUtils
  import URLEncoding
  
  -- FIXME !!!!!!
  grammarFile :: FilePath
  grammarFile = "/usr/local/share/gf-3.1/lib/alltenses/ParadigmsFin.gfo"
  
  grammarPath :: FilePath
  grammarPath = "/usr/local/share/gf-3.1/lib/prelude"
  
  main :: IO ()
  main = do initFastCGI
            r <- newCache readGrammar
            loopFastCGI (handleErrors (handleCGIErrors (fcgiMain r)))
  
  fcgiMain :: Cache SourceGrammar -> CGI CGIResult
  fcgiMain cache = liftIO (readCache cache grammarFile) >>= cgiMain
  
  readGrammar :: FilePath -> IO SourceGrammar
  readGrammar file = 
      do let opts = concatOptions [modifyFlags $ \fs -> fs { optVerbosity = Quiet },
                                   modifyFlags $ \fs -> fs { optLibraryPath = [grammarPath] }]
         mgr <- appIOE $ batchCompile opts [file]
         err (fail "Grammar loading error") return mgr
  
  cgiMain :: SourceGrammar -> CGI CGIResult
  cgiMain sgr =
      do path <- pathInfo
         json <- case path of
           "/eval"           -> do mjson <- return (doEval sgr) `ap` getTerm
                                   err (throwCGIError 400 "Evaluation error" . (:[])) return mjson
           _                 -> throwCGIError 404 "Not Found" ["Resource not found: " ++ path]
         outputJSON json
    where
      getTerm :: CGI String
      getTerm = do mt <- getInput "term"
                   maybe (throwCGIError 400 "No term given" ["No term given"]) (return . urlDecodeUnicode . UTF8.decodeString) mt
  
  doEval :: SourceGrammar -> String -> Err JSValue
  doEval sgr t = liftM termToJSValue $ eval sgr t 
  
  termToJSValue :: Term -> JSValue
  termToJSValue t =
    showJSON [toJSObject [("name", render name), ("value",render value)] | (name,value) <- ppTermTabular Unqualified t]
  
  eval :: SourceGrammar -> String -> Err Term
  eval sgr t = 
    case runP pExp (BS.pack t) of
      Right t       -> do mo <- maybe (Bad "no source grammar in scope") return $ greatestResource sgr
                          (t,_) <- runCheck (renameSourceTerm sgr mo t)
                          ((t,_),_) <- runCheck (inferLType sgr [] t)
                          computeConcrete sgr t
      Left  (_,msg) -> fail msg
  
  -- * General CGI and JSON stuff
  
  outputJSON :: JSON a => a -> CGI CGIResult
  outputJSON x = do setHeader "Content-Type" "text/json; charset=utf-8"
                    outputStrict $ UTF8.encodeString $ encode x
  
  outputStrict :: String -> CGI CGIResult
  outputStrict x | x == x = output x
                 | otherwise = fail "I am the pope."
  
  