module Main (main) where

import Core
import Database
import Handlers
import Logger
import Routes

import Control.Monad.Except          (ExceptT (ExceptT))
import Data.List
import Effectful
import Effectful.Error.Static        (Error, runErrorNoCallStack, throwError)
import Effectful.Reader.Static
import Network.Wai.Handler.Warp      (run)
import Network.Wai.Middleware.Static ((>->), staticPolicy, noDots, addBase)
import Servant hiding                ((:>), throwError, inject)
import qualified Servant             as S

--
-- Application
--
main :: IO ()
main = do
  pool   <- createConnectionPool "host=localhost dbname=demo"
  let env = AppEnv { pool = pool }
  runAppEff env $ databaseInit
  run port . middleware . serve proxy $ app env

app :: AppEnv -> Server AppAPI
app env = hoistServer proxy (Handler . ExceptT . runAppEff env) handlers

handlers :: ServerT AppAPI AppEff
handlers = rootHandler
      :<|> userListHandler
      :<|> userGetHandler
      :<|> userPostHandler
      :<|> userDeleteHandler

middleware :: Application -> Application
middleware = staticPolicy (noDots >-> addBase "data/assets/public")

runAppEff :: AppEnv -> AppEff a -> IO (Either ServerError a)
runAppEff env = runEff
              . runErrorNoCallStack
              . runReader env
              . runDatabaseIO
              . runLoggerPSQL
              . inject

port :: Int
port = 8080

proxy :: Proxy AppAPI
proxy = Proxy