-- | For use in trivial cases, such as in mocks, tests, etc.
module Cardano.Slotting.EpochInfo.Impl
  ( fixedEpochInfo,
    -- * Shortcuts
    fixedEpochInfoEpoch,
    fixedEpochInfoFirst,
  )
where

import Cardano.Slotting.EpochInfo.API
import Cardano.Slotting.Slot (EpochNo (..), EpochSize (..), SlotNo (..))
import Cardano.Slotting.Time (RelativeTime (..), SlotLength, getSlotLength)

-- | The 'EpochInfo' induced by assuming the epoch size and slot length are
-- fixed for the entire system lifetime
fixedEpochInfo :: Monad m => EpochSize -> SlotLength -> EpochInfo m
fixedEpochInfo :: EpochSize -> SlotLength -> EpochInfo m
fixedEpochInfo (EpochSize Word64
size) SlotLength
slotLength = EpochInfo :: forall (m :: * -> *).
(HasCallStack => EpochNo -> m EpochSize)
-> (HasCallStack => EpochNo -> m SlotNo)
-> (HasCallStack => SlotNo -> m EpochNo)
-> (HasCallStack => SlotNo -> m RelativeTime)
-> (HasCallStack => SlotNo -> m SlotLength)
-> EpochInfo m
EpochInfo
  { epochInfoSize_ :: HasCallStack => EpochNo -> m EpochSize
epochInfoSize_ = \EpochNo
_ ->
      EpochSize -> m EpochSize
forall (m :: * -> *) a. Monad m => a -> m a
return (EpochSize -> m EpochSize) -> EpochSize -> m EpochSize
forall a b. (a -> b) -> a -> b
$ Word64 -> EpochSize
EpochSize Word64
size,
    epochInfoFirst_ :: HasCallStack => EpochNo -> m SlotNo
epochInfoFirst_ = \EpochNo
e -> SlotNo -> m SlotNo
forall (m :: * -> *) a. Monad m => a -> m a
return (SlotNo -> m SlotNo) -> SlotNo -> m SlotNo
forall a b. (a -> b) -> a -> b
$ EpochSize -> EpochNo -> SlotNo
fixedEpochInfoFirst (Word64 -> EpochSize
EpochSize Word64
size) EpochNo
e,
    epochInfoEpoch_ :: HasCallStack => SlotNo -> m EpochNo
epochInfoEpoch_ = \SlotNo
sl -> EpochNo -> m EpochNo
forall (m :: * -> *) a. Monad m => a -> m a
return (EpochNo -> m EpochNo) -> EpochNo -> m EpochNo
forall a b. (a -> b) -> a -> b
$ EpochSize -> SlotNo -> EpochNo
fixedEpochInfoEpoch (Word64 -> EpochSize
EpochSize Word64
size) SlotNo
sl,
    epochInfoSlotToRelativeTime_ :: HasCallStack => SlotNo -> m RelativeTime
epochInfoSlotToRelativeTime_ = \(SlotNo Word64
slot) ->
      RelativeTime -> m RelativeTime
forall (m :: * -> *) a. Monad m => a -> m a
return (RelativeTime -> m RelativeTime) -> RelativeTime -> m RelativeTime
forall a b. (a -> b) -> a -> b
$ NominalDiffTime -> RelativeTime
RelativeTime (Word64 -> NominalDiffTime
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
slot NominalDiffTime -> NominalDiffTime -> NominalDiffTime
forall a. Num a => a -> a -> a
* SlotLength -> NominalDiffTime
getSlotLength SlotLength
slotLength),
    epochInfoSlotLength_ :: HasCallStack => SlotNo -> m SlotLength
epochInfoSlotLength_ = m SlotLength -> SlotNo -> m SlotLength
forall a b. a -> b -> a
const (m SlotLength -> SlotNo -> m SlotLength)
-> m SlotLength -> SlotNo -> m SlotLength
forall a b. (a -> b) -> a -> b
$ SlotLength -> m SlotLength
forall (f :: * -> *) a. Applicative f => a -> f a
pure SlotLength
slotLength
  }

-- | The pure computation underlying 'epochInfoFirst' applied to
-- 'fixedEpochInfo'
--
-- You don't need a 'SlotLength' for this.
fixedEpochInfoFirst :: EpochSize -> EpochNo -> SlotNo
fixedEpochInfoFirst :: EpochSize -> EpochNo -> SlotNo
fixedEpochInfoFirst (EpochSize Word64
size) (EpochNo Word64
epochNo) =
  Word64 -> SlotNo
SlotNo (Word64
epochNo Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
size)

-- | The pure computation underlying 'epochInfoEpoch' applied to
-- 'fixedEpochInfo'
--
-- You don't need a 'SlotLength' for this.
fixedEpochInfoEpoch :: EpochSize -> SlotNo -> EpochNo
fixedEpochInfoEpoch :: EpochSize -> SlotNo -> EpochNo
fixedEpochInfoEpoch (EpochSize Word64
size) (SlotNo Word64
slot) =
  Word64 -> EpochNo
EpochNo (Word64
slot Word64 -> Word64 -> Word64
forall a. Integral a => a -> a -> a
`div` Word64
size)