{-|
Complete the definition of the web app begun in App.hs.
This is always done in two files for (TH?) reasons.
-}

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

module Hledger.Web.Application
  ( makeApplication
  , makeApp
  , makeAppWith
  ) 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 (ServerMode(..), WebOpts(server_mode_), corsPolicy)

-- mkYesodDispatch creates our YesodDispatch instance. 
-- It complements the mkYesodData call in App.hs,
-- but must be in a separate file for (TH?) reasons.
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 opts' j' conf' = do
    app <- makeApp conf' opts'
    writeIORef (appJournal app) j'
    (logWare . (corsPolicy opts')) <$> toWaiApp app
  where
    logWare | development  = logStdoutDev
            | server_mode_ opts' `elem` [Serve, ServeJson] = logStdout
            | otherwise    = id

makeApp :: AppConfig DefaultEnv Extra -> WebOpts -> IO App
makeApp = makeAppWith nulljournal

-- Make an "App" (defined in App.hs), 
-- with the given Journal as its state
-- and the given "AppConfig" and "WebOpts" as its configuration.
makeAppWith :: Journal -> AppConfig DefaultEnv Extra -> WebOpts -> IO App
makeAppWith j' aconf wopts = do
  s    <- staticSite
  m    <- newManager defaultManagerSettings
  jref <- newIORef j'
  return App{
      settings    = aconf
    , getStatic   = s
    , httpManager = m
    , appOpts     = wopts
    , appJournal  = jref
    }
