{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}

-- | Parameters fixed in the genesis file: 'GenesisParameters'
--
module Bcc.Api.GenesisParameters (

    -- * Protocol paramaters fixed in the genesis file
    GenesisParameters(..),
    EpochSize(..),

    -- * Internal conversion functions
    fromSophieGenesis,

  ) where

import           Prelude

import           Data.Time (NominalDiffTime, UTCTime)

import           Data.Word (Word64)

import           Bcc.Slotting.Slot (EpochSize (..))

import qualified Bcc.Ledger.BaseTypes as Ledger
import qualified Sophie.Spec.Ledger.Genesis as Sophie

import           Bcc.Api.NetworkId
import           Bcc.Api.ProtocolParameters
import           Bcc.Api.Value


-- ----------------------------------------------------------------------------
-- Genesis parameters
--

data GenesisParameters =
     GenesisParameters {

       -- | The reference time the system started. The time of slot zero.
       -- The time epoch against which all Shardagnostic time slots are measured.
       --
       GenesisParameters -> UTCTime
protocolParamSystemStart :: UTCTime,

       -- | The network identifier for this blockchain instance. This
       -- distinguishes the mainnet from testnets, and different testnets from
       -- each other.
       --
       GenesisParameters -> NetworkId
protocolParamNetworkId :: NetworkId,

       -- | The Shardagnostic Optimum active slot coefficient, aka @f@.
       --
       GenesisParameters -> Rational
protocolParamActiveSlotsCoefficient :: Rational,

       -- | The Shardagnostic security paramaters, aka @k@. This is the maximum
       -- number of blocks the node would ever be prepared to roll back by.
       --
       -- Clients of the node following the chain should be prepared to handle
       -- the node switching forks up to this long.
       --
       GenesisParameters -> Int
protocolParamSecurity :: Int,

       -- | The Vested Sentry Protocol vestMultiple 
       -- 
       GenesisParameters -> Word64
protocolVestMultiple :: Word64,

       -- | The number of Shardagnostic time slots in an Shardagnostic epoch.
       --
       GenesisParameters -> EpochSize
protocolParamEpochLength :: EpochSize,

       -- | The time duration of a slot.
       --
       GenesisParameters -> NominalDiffTime
protocolParamSlotLength :: NominalDiffTime,

       -- | For Shardagnostic Optimum, the length of a KES period as a number of time
       -- slots. The KES keys get evolved once per KES period.
       --
       GenesisParameters -> Int
protocolParamSlotsPerKESPeriod :: Int,

       -- | The maximum number of times a KES key can be evolved before it is
       -- no longer considered valid. This can be less than the maximum number
       -- of times given the KES key size. For example the mainnet KES key size
       -- would allow 64 evolutions, but the max KES evolutions param is 62.
       --
       GenesisParameters -> Int
protocolParamMaxKESEvolutions ::  Int,

       -- | In the Sophie era, prior to decentralised governance, this is the
       -- number of genesis key delegates that need to agree for an update
       -- proposal to be enacted.
       --
       GenesisParameters -> Int
protocolParamUpdateQuorum ::  Int,

       -- | The maximum supply for Entropic. This determines the initial value
       -- of the reserves.
       --
       GenesisParameters -> Entropic
protocolParamMaxEntropicSupply :: Entropic,

       -- | The initial values of the updateable 'ProtocolParameters'.
       --
       GenesisParameters -> ProtocolParameters
protocolInitialUpdateableProtocolParameters :: ProtocolParameters
     }


-- ----------------------------------------------------------------------------
-- Conversion functions #TODO conversion fx VestedDelegs verify pertinenance
--

fromSophieGenesis :: Sophie.SophieGenesis era -> GenesisParameters
fromSophieGenesis :: SophieGenesis era -> GenesisParameters
fromSophieGenesis
    Sophie.SophieGenesis {
      UTCTime
sgSystemStart :: forall era. SophieGenesis era -> UTCTime
sgSystemStart :: UTCTime
Sophie.sgSystemStart
    , Word32
sgNetworkMagic :: forall era. SophieGenesis era -> Word32
sgNetworkMagic :: Word32
Sophie.sgNetworkMagic
    , Network
sgNetworkId :: forall era. SophieGenesis era -> Network
sgNetworkId :: Network
Sophie.sgNetworkId
    , PositiveUnitInterval
sgActiveSlotsCoeff :: forall era. SophieGenesis era -> PositiveUnitInterval
sgActiveSlotsCoeff :: PositiveUnitInterval
Sophie.sgActiveSlotsCoeff
    , Word64
sgSecurityParam :: forall era. SophieGenesis era -> Word64
sgSecurityParam :: Word64
Sophie.sgSecurityParam
    , Word64
sgVestMultiple :: forall era. SophieGenesis era -> Word64
sgVestMultiple :: Word64
Sophie.sgVestMultiple
    , EpochSize
sgEpochLength :: forall era. SophieGenesis era -> EpochSize
sgEpochLength :: EpochSize
Sophie.sgEpochLength
    , Word64
sgSlotsPerKESPeriod :: forall era. SophieGenesis era -> Word64
sgSlotsPerKESPeriod :: Word64
Sophie.sgSlotsPerKESPeriod
    , Word64
sgMaxKESEvolutions :: forall era. SophieGenesis era -> Word64
sgMaxKESEvolutions :: Word64
Sophie.sgMaxKESEvolutions
    , NominalDiffTime
sgSlotLength :: forall era. SophieGenesis era -> NominalDiffTime
sgSlotLength :: NominalDiffTime
Sophie.sgSlotLength
    , Word64
sgUpdateQuorum :: forall era. SophieGenesis era -> Word64
sgUpdateQuorum :: Word64
Sophie.sgUpdateQuorum
    , Word64
sgMaxEntropicSupply :: forall era. SophieGenesis era -> Word64
sgMaxEntropicSupply :: Word64
Sophie.sgMaxEntropicSupply
    , PParams era
sgProtocolParams :: forall era. SophieGenesis era -> PParams era
sgProtocolParams :: PParams era
Sophie.sgProtocolParams
    , sgGenDelegs :: forall era.
SophieGenesis era
-> Map (KeyHash 'Genesis (Crypto era)) (GenDelegPair (Crypto era))
Sophie.sgGenDelegs    = Map (KeyHash 'Genesis (Crypto era)) (GenDelegPair (Crypto era))
_  -- unused, might be of interest
    , sgVestedDelegs :: forall era.
SophieGenesis era
-> Map
     (KeyHash 'Vested (Crypto era)) (VestedDelegPair (Crypto era))
Sophie.sgVestedDelegs  = Map (KeyHash 'Vested (Crypto era)) (VestedDelegPair (Crypto era))
_  -- unused, might be if interest
    , sgInitialFunds :: forall era. SophieGenesis era -> Map (Addr (Crypto era)) Coin
Sophie.sgInitialFunds = Map (Addr (Crypto era)) Coin
_  -- unused, not retained by the node
    , sgStaking :: forall era. SophieGenesis era -> SophieGenesisStaking (Crypto era)
Sophie.sgStaking      = SophieGenesisStaking (Crypto era)
_  -- unused, not retained by the node
    } =
    GenesisParameters :: UTCTime
-> NetworkId
-> Rational
-> Int
-> Word64
-> EpochSize
-> NominalDiffTime
-> Int
-> Int
-> Int
-> Entropic
-> ProtocolParameters
-> GenesisParameters
GenesisParameters {
      protocolParamSystemStart :: UTCTime
protocolParamSystemStart            = UTCTime
sgSystemStart
    , protocolParamNetworkId :: NetworkId
protocolParamNetworkId              = Network -> NetworkMagic -> NetworkId
fromSophieNetwork Network
sgNetworkId
                                              (Word32 -> NetworkMagic
NetworkMagic Word32
sgNetworkMagic)
    , protocolParamActiveSlotsCoefficient :: Rational
protocolParamActiveSlotsCoefficient = PositiveUnitInterval -> Rational
forall r. BoundedRational r => r -> Rational
Ledger.unboundRational
                                              PositiveUnitInterval
sgActiveSlotsCoeff
    , protocolParamSecurity :: Int
protocolParamSecurity               = Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
sgSecurityParam
    , protocolVestMultiple :: Word64
protocolVestMultiple                  = Word64
sgVestMultiple
    , protocolParamEpochLength :: EpochSize
protocolParamEpochLength            = EpochSize
sgEpochLength
    , protocolParamSlotLength :: NominalDiffTime
protocolParamSlotLength             = NominalDiffTime
sgSlotLength
    , protocolParamSlotsPerKESPeriod :: Int
protocolParamSlotsPerKESPeriod      = Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
sgSlotsPerKESPeriod
    , protocolParamMaxKESEvolutions :: Int
protocolParamMaxKESEvolutions       = Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
sgMaxKESEvolutions
    , protocolParamUpdateQuorum :: Int
protocolParamUpdateQuorum           = Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
sgUpdateQuorum
    , protocolParamMaxEntropicSupply :: Entropic
protocolParamMaxEntropicSupply         = Integer -> Entropic
Entropic
                                              (Word64 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
sgMaxEntropicSupply)
    , protocolInitialUpdateableProtocolParameters :: ProtocolParameters
protocolInitialUpdateableProtocolParameters = PParams era -> ProtocolParameters
forall ledgerera. PParams ledgerera -> ProtocolParameters
fromSophiePParams
                                                      PParams era
sgProtocolParams
    }