module TimerWheel.Internal.Timestamp
  ( Timestamp (..),
    epoch,
    minus,
    now,
    plus,
    TimerWheel.Internal.Timestamp.rem,
  )
where

import Data.Coerce (coerce)
import Data.Word (Word64)
import GHC.Clock (getMonotonicTimeNSec)
import TimerWheel.Internal.Micros (Micros (..))

newtype Timestamp
  = Timestamp Word64
  deriving stock (Timestamp -> Timestamp -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Timestamp -> Timestamp -> Bool
$c/= :: Timestamp -> Timestamp -> Bool
== :: Timestamp -> Timestamp -> Bool
$c== :: Timestamp -> Timestamp -> Bool
Eq, Eq Timestamp
Timestamp -> Timestamp -> Bool
Timestamp -> Timestamp -> Ordering
Timestamp -> Timestamp -> Timestamp
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 :: Timestamp -> Timestamp -> Timestamp
$cmin :: Timestamp -> Timestamp -> Timestamp
max :: Timestamp -> Timestamp -> Timestamp
$cmax :: Timestamp -> Timestamp -> Timestamp
>= :: Timestamp -> Timestamp -> Bool
$c>= :: Timestamp -> Timestamp -> Bool
> :: Timestamp -> Timestamp -> Bool
$c> :: Timestamp -> Timestamp -> Bool
<= :: Timestamp -> Timestamp -> Bool
$c<= :: Timestamp -> Timestamp -> Bool
< :: Timestamp -> Timestamp -> Bool
$c< :: Timestamp -> Timestamp -> Bool
compare :: Timestamp -> Timestamp -> Ordering
$ccompare :: Timestamp -> Timestamp -> Ordering
Ord)

-- Which epoch does this correspond to, if they are measured in chunks of the given number of milliseconds?
epoch :: Micros -> Timestamp -> Word64
epoch :: Micros -> Timestamp -> Word64
epoch (Micros Word64
chunk) (Timestamp Word64
timestamp) =
  Word64
timestamp forall a. Integral a => a -> a -> a
`div` Word64
chunk

minus :: Timestamp -> Timestamp -> Micros
minus :: Timestamp -> Timestamp -> Micros
minus =
  coerce :: forall a b. Coercible a b => a -> b
coerce ((-) @Word64)

now :: IO Timestamp
now :: IO Timestamp
now = do
  Word64
nanos <- IO Word64
getMonotonicTimeNSec
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word64 -> Timestamp
Timestamp (Word64
nanos forall a. Integral a => a -> a -> a
`div` Word64
1000))

plus :: Timestamp -> Micros -> Timestamp
plus :: Timestamp -> Micros -> Timestamp
plus =
  coerce :: forall a b. Coercible a b => a -> b
coerce (forall a. Num a => a -> a -> a
(+) @Word64)

rem :: Timestamp -> Micros -> Micros
rem :: Timestamp -> Micros -> Micros
rem =
  coerce :: forall a b. Coercible a b => a -> b
coerce (forall a. Integral a => a -> a -> a
Prelude.rem @Word64)