content: {-# LANGUAGE DeriveAnyClass #-}
  {-# LANGUAGE DeriveGeneric #-}
  {-# LANGUAGE OverloadedStrings #-}
  
  {-# OPTIONS -fno-warn-deprecations #-}
  
  module Blockchain.EthConf.Model where
  
  -- These are the aspects EthConf that don't require unsafePerformIO
  
  import qualified Data.ByteString as B
  import qualified Data.ByteString.Char8 as C8
  import Data.Ratio
  import Data.Yaml
  import qualified Database.PostgreSQL.Simple as PS (ConnectInfo (..), postgreSQLConnectionString)
  import qualified Database.Redis as Redis
  import GHC.Generics
  
  postgreSQLConnectionString :: SqlConf -> B.ByteString
  postgreSQLConnectionString sqlc =
    PS.postgreSQLConnectionString
      PS.ConnectInfo
        { PS.connectHost = host sqlc,
          PS.connectPort = fromIntegral $ port sqlc,
          PS.connectUser = user sqlc,
          PS.connectPassword = password sqlc,
          PS.connectDatabase = database sqlc
        }
  
  redisConnection :: RedisBlockDBConf -> Redis.ConnectInfo
  redisConnection r =
    Redis.defaultConnectInfo
      { Redis.connectHost = redisHost r,
        Redis.connectPort = Redis.PortNumber $ fromIntegral (redisPort r),
        Redis.connectAuth = C8.pack <$> redisAuth r,
        Redis.connectDatabase = redisDBNumber r,
        Redis.connectMaxConnections = redisMaxConnections r,
        Redis.connectMaxIdleTime = fromRational (redisMaxIdleTime r % 1)
      }
  
  data EthConf = EthConf
    { sqlConfig :: SqlConf,
      cirrusConfig :: SqlConf,
      redisBlockDBConfig :: RedisBlockDBConf,
      kafkaConfig :: KafkaConf,
      levelDBConfig :: LevelDBConf,
      quarryConfig :: QuarryConf,
      blockConfig :: BlockConf,
      discoveryConfig :: DiscoveryConf
    }
    deriving (Show, Eq, Generic, FromJSON, ToJSON)
  
  data DiscoveryConf = DiscoveryConf
    { discoveryPort :: Int,
      minAvailablePeers :: Int
    }
    deriving (Show, Eq, Generic, FromJSON, ToJSON)
  
  data SqlConf = SqlConf
    { user :: String,
      password :: String,
      host :: String,
      port :: Int,
      database :: String,
      poolsize :: Int
    }
    deriving (Show, Eq, Generic, FromJSON, ToJSON)
  
  data KafkaConf = KafkaConf
    { kafkaHost :: String,
      kafkaPort :: Int
    }
    deriving (Show, Eq, Generic, FromJSON, ToJSON)
  
  data RedisBlockDBConf = RedisBlockDBConf
    { redisHost :: String,
      redisPort :: Int,
      redisAuth :: Maybe String,
      redisDBNumber :: Integer,
      redisMaxConnections :: Int,
      redisMaxIdleTime :: Integer
    }
    deriving (Show, Eq, Generic, FromJSON, ToJSON)
  
  data LevelDBConf = LevelDBConf
    { table :: String,
      path :: String
    }
    deriving (Show, Eq, Generic, FromJSON, ToJSON)
  
  data QuarryConf = QuarryConf
    { coinbaseAddress :: String,
      lazyBlocks :: Bool
    }
    deriving (Show, Eq, Generic, FromJSON, ToJSON)
  
  data BlockConf = BlockConf
    { blockTime :: Integer,
      minBlockDifficulty :: Integer
    }
    deriving (Show, Eq, Generic, FromJSON, ToJSON)
  