{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ViewPatterns #-}

module Hledger.Web.Application
  ( makeApplication
  , makeFoundation
  , makeFoundationWith
  ) where

import Data.IORef (newIORef, writeIORef)
import Network.Wai.Middleware.RequestLogger (logStdoutDev, logStdout)
import Network.HTTP.Client (defaultManagerSettings)
import Network.HTTP.Conduit (newManager)
import Yesod.Default.Config

import Hledger.Data (Journal, nulljournal)

import Hledger.Web.Handler.AddR
import Hledger.Web.Handler.MiscR
import Hledger.Web.Handler.EditR
import Hledger.Web.Handler.UploadR
import Hledger.Web.Handler.JournalR
import Hledger.Web.Handler.RegisterR
import Hledger.Web.Import
import Hledger.Web.WebOptions (WebOpts(serve_,serve_api_), corsPolicy)

-- This line actually creates our YesodDispatch instance. It is the second half
-- of the call to mkYesodData which occurs in Foundation.hs. Please see the
-- comments there for more details.
mkYesodDispatch "App" resourcesApp

-- This function allocates resources (such as a database connection pool),
-- performs initialization and creates a WAI application. This is also the
-- place to put your migrate statements to have automatic database
-- migrations handled by Yesod.
makeApplication :: WebOpts -> Journal -> AppConfig DefaultEnv Extra -> IO Application
makeApplication :: WebOpts -> Journal -> AppConfig DefaultEnv Extra -> IO Application
makeApplication WebOpts
opts' Journal
j' AppConfig DefaultEnv Extra
conf' = do
    App
foundation <- AppConfig DefaultEnv Extra -> WebOpts -> IO App
makeFoundation AppConfig DefaultEnv Extra
conf' WebOpts
opts'
    IORef Journal -> Journal -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef (App -> IORef Journal
appJournal App
foundation) Journal
j'
    (Middleware
logWare Middleware -> Middleware -> Middleware
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (WebOpts -> Middleware
corsPolicy WebOpts
opts')) Middleware -> IO Application -> IO Application
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> App -> IO Application
forall site. YesodDispatch site => site -> IO Application
toWaiApp App
foundation
  where
    logWare :: Middleware
logWare | Bool
development  = Middleware
logStdoutDev
            | WebOpts -> Bool
serve_ WebOpts
opts' Bool -> Bool -> Bool
|| WebOpts -> Bool
serve_api_ WebOpts
opts' = Middleware
logStdout
            | Bool
otherwise    = Middleware
forall a. a -> a
id

makeFoundation :: AppConfig DefaultEnv Extra -> WebOpts -> IO App
makeFoundation :: AppConfig DefaultEnv Extra -> WebOpts -> IO App
makeFoundation AppConfig DefaultEnv Extra
conf WebOpts
opts' = do
    Manager
manager <- ManagerSettings -> IO Manager
newManager ManagerSettings
defaultManagerSettings
    Static
s <- IO Static
staticSite
    IORef Journal
jref <- Journal -> IO (IORef Journal)
forall a. a -> IO (IORef a)
newIORef Journal
nulljournal
    App -> IO App
forall (m :: * -> *) a. Monad m => a -> m a
return (App -> IO App) -> App -> IO App
forall a b. (a -> b) -> a -> b
$ AppConfig DefaultEnv Extra
-> Static -> Manager -> WebOpts -> IORef Journal -> App
App AppConfig DefaultEnv Extra
conf Static
s Manager
manager WebOpts
opts' IORef Journal
jref

-- Make a Foundation with the given Journal as its state.
makeFoundationWith :: Journal -> AppConfig DefaultEnv Extra -> WebOpts -> IO App
makeFoundationWith :: Journal -> AppConfig DefaultEnv Extra -> WebOpts -> IO App
makeFoundationWith Journal
j' AppConfig DefaultEnv Extra
conf WebOpts
opts' = do
    Manager
manager <- ManagerSettings -> IO Manager
newManager ManagerSettings
defaultManagerSettings
    Static
s <- IO Static
staticSite
    IORef Journal
jref <- Journal -> IO (IORef Journal)
forall a. a -> IO (IORef a)
newIORef Journal
j'
    App -> IO App
forall (m :: * -> *) a. Monad m => a -> m a
return (App -> IO App) -> App -> IO App
forall a b. (a -> b) -> a -> b
$ AppConfig DefaultEnv Extra
-> Static -> Manager -> WebOpts -> IORef Journal -> App
App AppConfig DefaultEnv Extra
conf Static
s Manager
manager WebOpts
opts' IORef Journal
jref