{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}

module Simplex.Chat.Store.AppSettings where

import Control.Monad (join)
import Control.Monad.IO.Class (liftIO)
import qualified Data.Aeson as J
import Data.Maybe (fromMaybe)
import Simplex.Chat.AppSettings (AppSettings (..), combineAppSettings, defaultAppSettings, defaultParseAppSettings)
import Simplex.Messaging.Agent.Store.AgentStore (maybeFirstRow)
import qualified Simplex.Messaging.Agent.Store.DB as DB
#if defined(dbPostgres)
import Database.PostgreSQL.Simple (Only (..))
#else
import Database.SQLite.Simple (Only (..))
#endif

saveAppSettings :: DB.Connection -> AppSettings -> IO ()
saveAppSettings :: Connection -> AppSettings -> IO ()
saveAppSettings Connection
db AppSettings
appSettings = do
  Connection -> Query -> IO ()
DB.execute_ Connection
db Query
"DELETE FROM app_settings"
  Connection -> Query -> Only ByteString -> IO ()
forall q. ToRow q => Connection -> Query -> q -> IO ()
DB.execute Connection
db Query
"INSERT INTO app_settings (app_settings) VALUES (?)" (ByteString -> Only ByteString
forall a. a -> Only a
Only (ByteString -> Only ByteString) -> ByteString -> Only ByteString
forall a b. (a -> b) -> a -> b
$ AppSettings -> ByteString
forall a. ToJSON a => a -> ByteString
J.encode AppSettings
appSettings)

getAppSettings :: DB.Connection -> Maybe AppSettings -> IO AppSettings
getAppSettings :: Connection -> Maybe AppSettings -> IO AppSettings
getAppSettings Connection
db Maybe AppSettings
platformDefaults = do
  Maybe AppSettings
stored_ <- Maybe (Maybe AppSettings) -> Maybe AppSettings
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (Maybe (Maybe AppSettings) -> Maybe AppSettings)
-> IO (Maybe (Maybe AppSettings)) -> IO (Maybe AppSettings)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO (Maybe (Maybe AppSettings)) -> IO (Maybe (Maybe AppSettings))
forall a. IO a -> IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO ((Only ByteString -> Maybe AppSettings)
-> IO [Only ByteString] -> IO (Maybe (Maybe AppSettings))
forall (f :: * -> *) a b.
Functor f =>
(a -> b) -> f [a] -> f (Maybe b)
maybeFirstRow (ByteString -> Maybe AppSettings
forall a. FromJSON a => ByteString -> Maybe a
J.decodeStrict (ByteString -> Maybe AppSettings)
-> (Only ByteString -> ByteString)
-> Only ByteString
-> Maybe AppSettings
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Only ByteString -> ByteString
forall a. Only a -> a
fromOnly) (IO [Only ByteString] -> IO (Maybe (Maybe AppSettings)))
-> IO [Only ByteString] -> IO (Maybe (Maybe AppSettings))
forall a b. (a -> b) -> a -> b
$ Connection -> Query -> IO [Only ByteString]
forall r. FromRow r => Connection -> Query -> IO [r]
DB.query_ Connection
db Query
"SELECT app_settings FROM app_settings")
  AppSettings -> IO AppSettings
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (AppSettings -> IO AppSettings) -> AppSettings -> IO AppSettings
forall a b. (a -> b) -> a -> b
$ AppSettings -> AppSettings -> AppSettings
combineAppSettings (AppSettings -> Maybe AppSettings -> AppSettings
forall a. a -> Maybe a -> a
fromMaybe AppSettings
defaultAppSettings Maybe AppSettings
platformDefaults) (AppSettings -> Maybe AppSettings -> AppSettings
forall a. a -> Maybe a -> a
fromMaybe AppSettings
defaultParseAppSettings Maybe AppSettings
stored_)