module Ribosome.System.Time where

import Control.Concurrent (threadDelay)
import Data.Hourglass (Elapsed(Elapsed), ElapsedP(ElapsedP), NanoSeconds(NanoSeconds), Seconds(Seconds))
import Data.Time.Clock.POSIX (getPOSIXTime)
import GHC.Float (word2Double)

epochSeconds :: MonadIO m => m Int
epochSeconds :: m Int
epochSeconds = IO Int -> m Int
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Int -> m Int) -> IO Int -> m Int
forall a b. (a -> b) -> a -> b
$ POSIXTime -> Int
forall a b. (RealFrac a, Integral b) => a -> b
round (POSIXTime -> Int) -> IO POSIXTime -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO POSIXTime
getPOSIXTime

usleep :: MonadIO m => Double -> m ()
usleep :: Double -> m ()
usleep =
  IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> (Double -> IO ()) -> Double -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> IO ()
threadDelay (Int -> IO ()) -> (Double -> Int) -> Double -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
round

sleep :: MonadIO m => Double -> m ()
sleep :: Double -> m ()
sleep Double
seconds =
  Double -> m ()
forall (m :: * -> *). MonadIO m => Double -> m ()
usleep (Double -> m ()) -> Double -> m ()
forall a b. (a -> b) -> a -> b
$ Double
seconds Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
1e6

sleepW :: MonadIO m => Word -> m ()
sleepW :: Word -> m ()
sleepW = Double -> m ()
forall (m :: * -> *). MonadIO m => Double -> m ()
sleep (Double -> m ()) -> (Word -> Double) -> Word -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word -> Double
word2Double

secondsP :: Double -> ElapsedP
secondsP :: Double -> ElapsedP
secondsP Double
s =
  Elapsed -> NanoSeconds -> ElapsedP
ElapsedP (Seconds -> Elapsed
Elapsed (Int64 -> Seconds
Seconds (Int64 -> Seconds) -> Int64 -> Seconds
forall a b. (a -> b) -> a -> b
$ Double -> Int64
forall a b. (RealFrac a, Integral b) => a -> b
floor Double
s)) (Int64 -> NanoSeconds
NanoSeconds Int64
nano)
  where
    nano :: Int64
nano =
      Double -> Int64
forall a b. (RealFrac a, Integral b) => a -> b
round (Double
s Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
1000000000) Int64 -> Int64 -> Int64
forall a. Integral a => a -> a -> a
`mod` Int64
1000000000