module System.Metrics.Prometheus.Metric.Gauge (
    Gauge,
    GaugeSample (..),
    new,
    add,
    sub,
    inc,
    dec,
    set,
    sample,
    modifyAndSample,
) where

import Control.Applicative ((<$>))
import Data.IORef (IORef, atomicModifyIORef', newIORef)


newtype Gauge = Gauge {Gauge -> IORef Double
unGauge :: IORef Double}
newtype GaugeSample = GaugeSample {GaugeSample -> Double
unGaugeSample :: Double}


new :: IO Gauge
new :: IO Gauge
new = IORef Double -> Gauge
Gauge forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. a -> IO (IORef a)
newIORef Double
0


modifyAndSample :: (Double -> Double) -> Gauge -> IO GaugeSample
modifyAndSample :: (Double -> Double) -> Gauge -> IO GaugeSample
modifyAndSample Double -> Double
f = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' Double -> (Double, GaugeSample)
g forall b c a. (b -> c) -> (a -> b) -> a -> c
. Gauge -> IORef Double
unGauge
  where
    g :: Double -> (Double, GaugeSample)
g Double
v = (Double -> Double
f Double
v, Double -> GaugeSample
GaugeSample forall a b. (a -> b) -> a -> b
$ Double -> Double
f Double
v)


add :: Double -> Gauge -> IO ()
add :: Double -> Gauge -> IO ()
add Double
x Gauge
g = (Double -> Double) -> Gauge -> IO GaugeSample
modifyAndSample (forall a. Num a => a -> a -> a
+ Double
x) Gauge
g forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (f :: * -> *) a. Applicative f => a -> f a
pure ()


sub :: Double -> Gauge -> IO ()
sub :: Double -> Gauge -> IO ()
sub Double
x Gauge
g = (Double -> Double) -> Gauge -> IO GaugeSample
modifyAndSample (forall a. Num a => a -> a -> a
subtract Double
x) Gauge
g forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (f :: * -> *) a. Applicative f => a -> f a
pure ()


inc :: Gauge -> IO ()
inc :: Gauge -> IO ()
inc = Double -> Gauge -> IO ()
add Double
1


dec :: Gauge -> IO ()
dec :: Gauge -> IO ()
dec = Double -> Gauge -> IO ()
sub Double
1


set :: Double -> Gauge -> IO ()
set :: Double -> Gauge -> IO ()
set Double
x Gauge
g = (Double -> Double) -> Gauge -> IO GaugeSample
modifyAndSample (forall a b. a -> b -> a
const Double
x) Gauge
g forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (f :: * -> *) a. Applicative f => a -> f a
pure ()


sample :: Gauge -> IO GaugeSample
sample :: Gauge -> IO GaugeSample
sample = (Double -> Double) -> Gauge -> IO GaugeSample
modifyAndSample forall a. a -> a
id