{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Shelley.Spec.Ledger.Slot
  ( SlotNo (..),
    Duration (..),
    (-*),
    (+*),
    (*-),
    EpochNo (..),
    EpochSize (..),
    EpochInfo,
    -- Block number
    BlockNo (..),
    epochInfoEpoch,
    epochInfoFirst,
    epochInfoSize,
  )
where

import Cardano.Slotting.Block (BlockNo (..))
import Cardano.Slotting.EpochInfo (EpochInfo)
import qualified Cardano.Slotting.EpochInfo as EI
import Cardano.Slotting.Slot (EpochNo (..), EpochSize (..), SlotNo (..))
import Control.Monad.Trans (lift)
import Data.Functor.Identity (Identity)
import Data.Word (Word64)
import GHC.Generics (Generic)
import GHC.Stack (HasCallStack)
import NoThunks.Class (NoThunks (..))
import Quiet
import Shelley.Spec.Ledger.BaseTypes (ShelleyBase)

newtype Duration = Duration {Duration -> Word64
unDuration :: Word64}
  deriving (Duration -> Duration -> Bool
(Duration -> Duration -> Bool)
-> (Duration -> Duration -> Bool) -> Eq Duration
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Duration -> Duration -> Bool
$c/= :: Duration -> Duration -> Bool
== :: Duration -> Duration -> Bool
$c== :: Duration -> Duration -> Bool
Eq, (forall x. Duration -> Rep Duration x)
-> (forall x. Rep Duration x -> Duration) -> Generic Duration
forall x. Rep Duration x -> Duration
forall x. Duration -> Rep Duration x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Duration x -> Duration
$cfrom :: forall x. Duration -> Rep Duration x
Generic, Eq Duration
Eq Duration
-> (Duration -> Duration -> Ordering)
-> (Duration -> Duration -> Bool)
-> (Duration -> Duration -> Bool)
-> (Duration -> Duration -> Bool)
-> (Duration -> Duration -> Bool)
-> (Duration -> Duration -> Duration)
-> (Duration -> Duration -> Duration)
-> Ord Duration
Duration -> Duration -> Bool
Duration -> Duration -> Ordering
Duration -> Duration -> Duration
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Duration -> Duration -> Duration
$cmin :: Duration -> Duration -> Duration
max :: Duration -> Duration -> Duration
$cmax :: Duration -> Duration -> Duration
>= :: Duration -> Duration -> Bool
$c>= :: Duration -> Duration -> Bool
> :: Duration -> Duration -> Bool
$c> :: Duration -> Duration -> Bool
<= :: Duration -> Duration -> Bool
$c<= :: Duration -> Duration -> Bool
< :: Duration -> Duration -> Bool
$c< :: Duration -> Duration -> Bool
compare :: Duration -> Duration -> Ordering
$ccompare :: Duration -> Duration -> Ordering
$cp1Ord :: Eq Duration
Ord, Context -> Duration -> IO (Maybe ThunkInfo)
Proxy Duration -> String
(Context -> Duration -> IO (Maybe ThunkInfo))
-> (Context -> Duration -> IO (Maybe ThunkInfo))
-> (Proxy Duration -> String)
-> NoThunks Duration
forall a.
(Context -> a -> IO (Maybe ThunkInfo))
-> (Context -> a -> IO (Maybe ThunkInfo))
-> (Proxy a -> String)
-> NoThunks a
showTypeOf :: Proxy Duration -> String
$cshowTypeOf :: Proxy Duration -> String
wNoThunks :: Context -> Duration -> IO (Maybe ThunkInfo)
$cwNoThunks :: Context -> Duration -> IO (Maybe ThunkInfo)
noThunks :: Context -> Duration -> IO (Maybe ThunkInfo)
$cnoThunks :: Context -> Duration -> IO (Maybe ThunkInfo)
NoThunks, Integer -> Duration
Duration -> Duration
Duration -> Duration -> Duration
(Duration -> Duration -> Duration)
-> (Duration -> Duration -> Duration)
-> (Duration -> Duration -> Duration)
-> (Duration -> Duration)
-> (Duration -> Duration)
-> (Duration -> Duration)
-> (Integer -> Duration)
-> Num Duration
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> Duration
$cfromInteger :: Integer -> Duration
signum :: Duration -> Duration
$csignum :: Duration -> Duration
abs :: Duration -> Duration
$cabs :: Duration -> Duration
negate :: Duration -> Duration
$cnegate :: Duration -> Duration
* :: Duration -> Duration -> Duration
$c* :: Duration -> Duration -> Duration
- :: Duration -> Duration -> Duration
$c- :: Duration -> Duration -> Duration
+ :: Duration -> Duration -> Duration
$c+ :: Duration -> Duration -> Duration
Num, Enum Duration
Real Duration
Real Duration
-> Enum Duration
-> (Duration -> Duration -> Duration)
-> (Duration -> Duration -> Duration)
-> (Duration -> Duration -> Duration)
-> (Duration -> Duration -> Duration)
-> (Duration -> Duration -> (Duration, Duration))
-> (Duration -> Duration -> (Duration, Duration))
-> (Duration -> Integer)
-> Integral Duration
Duration -> Integer
Duration -> Duration -> (Duration, Duration)
Duration -> Duration -> Duration
forall a.
Real a
-> Enum a
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
toInteger :: Duration -> Integer
$ctoInteger :: Duration -> Integer
divMod :: Duration -> Duration -> (Duration, Duration)
$cdivMod :: Duration -> Duration -> (Duration, Duration)
quotRem :: Duration -> Duration -> (Duration, Duration)
$cquotRem :: Duration -> Duration -> (Duration, Duration)
mod :: Duration -> Duration -> Duration
$cmod :: Duration -> Duration -> Duration
div :: Duration -> Duration -> Duration
$cdiv :: Duration -> Duration -> Duration
rem :: Duration -> Duration -> Duration
$crem :: Duration -> Duration -> Duration
quot :: Duration -> Duration -> Duration
$cquot :: Duration -> Duration -> Duration
$cp2Integral :: Enum Duration
$cp1Integral :: Real Duration
Integral, Num Duration
Ord Duration
Num Duration
-> Ord Duration -> (Duration -> Rational) -> Real Duration
Duration -> Rational
forall a. Num a -> Ord a -> (a -> Rational) -> Real a
toRational :: Duration -> Rational
$ctoRational :: Duration -> Rational
$cp2Real :: Ord Duration
$cp1Real :: Num Duration
Real, Int -> Duration
Duration -> Int
Duration -> [Duration]
Duration -> Duration
Duration -> Duration -> [Duration]
Duration -> Duration -> Duration -> [Duration]
(Duration -> Duration)
-> (Duration -> Duration)
-> (Int -> Duration)
-> (Duration -> Int)
-> (Duration -> [Duration])
-> (Duration -> Duration -> [Duration])
-> (Duration -> Duration -> [Duration])
-> (Duration -> Duration -> Duration -> [Duration])
-> Enum Duration
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Duration -> Duration -> Duration -> [Duration]
$cenumFromThenTo :: Duration -> Duration -> Duration -> [Duration]
enumFromTo :: Duration -> Duration -> [Duration]
$cenumFromTo :: Duration -> Duration -> [Duration]
enumFromThen :: Duration -> Duration -> [Duration]
$cenumFromThen :: Duration -> Duration -> [Duration]
enumFrom :: Duration -> [Duration]
$cenumFrom :: Duration -> [Duration]
fromEnum :: Duration -> Int
$cfromEnum :: Duration -> Int
toEnum :: Int -> Duration
$ctoEnum :: Int -> Duration
pred :: Duration -> Duration
$cpred :: Duration -> Duration
succ :: Duration -> Duration
$csucc :: Duration -> Duration
Enum)
  deriving (Int -> Duration -> ShowS
[Duration] -> ShowS
Duration -> String
(Int -> Duration -> ShowS)
-> (Duration -> String) -> ([Duration] -> ShowS) -> Show Duration
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Duration] -> ShowS
$cshowList :: [Duration] -> ShowS
show :: Duration -> String
$cshow :: Duration -> String
showsPrec :: Int -> Duration -> ShowS
$cshowsPrec :: Int -> Duration -> ShowS
Show) via Quiet Duration

instance Semigroup Duration where
  (Duration Word64
x) <> :: Duration -> Duration -> Duration
<> (Duration Word64
y) = Word64 -> Duration
Duration (Word64 -> Duration) -> Word64 -> Duration
forall a b. (a -> b) -> a -> b
$ Word64
x Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
y

instance Monoid Duration where
  mempty :: Duration
mempty = Word64 -> Duration
Duration Word64
0
  mappend :: Duration -> Duration -> Duration
mappend = Duration -> Duration -> Duration
forall a. Semigroup a => a -> a -> a
(<>)

(-*) :: SlotNo -> SlotNo -> Duration
(SlotNo Word64
s) -* :: SlotNo -> SlotNo -> Duration
-* (SlotNo Word64
t) = Word64 -> Duration
Duration (if Word64
s Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
t then Word64
s Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
t else Word64
t Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
s)

(+*) :: SlotNo -> Duration -> SlotNo
(SlotNo Word64
s) +* :: SlotNo -> Duration -> SlotNo
+* (Duration Word64
d) = Word64 -> SlotNo
SlotNo (Word64
s Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
d)

-- | Subtract a duration from a slot
(*-) :: SlotNo -> Duration -> SlotNo
(SlotNo Word64
s) *- :: SlotNo -> Duration -> SlotNo
*- (Duration Word64
d) = Word64 -> SlotNo
SlotNo (if Word64
s Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
d then Word64
s Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
d else Word64
0)

epochInfoEpoch ::
  HasCallStack =>
  EpochInfo Identity ->
  SlotNo ->
  ShelleyBase EpochNo
epochInfoEpoch :: EpochInfo Identity -> SlotNo -> ShelleyBase EpochNo
epochInfoEpoch EpochInfo Identity
ei = Identity EpochNo -> ShelleyBase EpochNo
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (Identity EpochNo -> ShelleyBase EpochNo)
-> (SlotNo -> Identity EpochNo) -> SlotNo -> ShelleyBase EpochNo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EpochInfo Identity -> SlotNo -> Identity EpochNo
forall (m :: * -> *).
HasCallStack =>
EpochInfo m -> SlotNo -> m EpochNo
EI.epochInfoEpoch EpochInfo Identity
ei

epochInfoFirst ::
  HasCallStack =>
  EpochInfo Identity ->
  EpochNo ->
  ShelleyBase SlotNo
epochInfoFirst :: EpochInfo Identity -> EpochNo -> ShelleyBase SlotNo
epochInfoFirst EpochInfo Identity
ei = Identity SlotNo -> ShelleyBase SlotNo
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (Identity SlotNo -> ShelleyBase SlotNo)
-> (EpochNo -> Identity SlotNo) -> EpochNo -> ShelleyBase SlotNo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EpochInfo Identity -> EpochNo -> Identity SlotNo
forall (m :: * -> *).
HasCallStack =>
EpochInfo m -> EpochNo -> m SlotNo
EI.epochInfoFirst EpochInfo Identity
ei

epochInfoSize ::
  HasCallStack =>
  EpochInfo Identity ->
  EpochNo ->
  ShelleyBase EpochSize
epochInfoSize :: EpochInfo Identity -> EpochNo -> ShelleyBase EpochSize
epochInfoSize EpochInfo Identity
ei = Identity EpochSize -> ShelleyBase EpochSize
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (Identity EpochSize -> ShelleyBase EpochSize)
-> (EpochNo -> Identity EpochSize)
-> EpochNo
-> ShelleyBase EpochSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EpochInfo Identity -> EpochNo -> Identity EpochSize
forall (m :: * -> *).
HasCallStack =>
EpochInfo m -> EpochNo -> m EpochSize
EI.epochInfoSize EpochInfo Identity
ei