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 Servant hiding           ((:>), throwError)
import qualified Servant        as S

--
-- Application
--
main :: IO ()
main = do
  pool   <- createConnectionPool 
  let env = AppEnv { pool = pool }
  runAppEff env $ databaseInit
  run port . 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

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

port :: Int
port = 8080

proxy :: Proxy AppAPI
proxy = Proxy