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 (IORef Double -> Gauge) -> IO (IORef Double) -> IO Gauge
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Double -> IO (IORef Double)
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 = (IORef Double
 -> (Double -> (Double, GaugeSample)) -> IO GaugeSample)
-> (Double -> (Double, GaugeSample))
-> IORef Double
-> IO GaugeSample
forall a b c. (a -> b -> c) -> b -> a -> c
flip IORef Double -> (Double -> (Double, GaugeSample)) -> IO GaugeSample
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' Double -> (Double, GaugeSample)
g (IORef Double -> IO GaugeSample)
-> (Gauge -> IORef Double) -> Gauge -> IO GaugeSample
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 (Double -> GaugeSample) -> Double -> 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 (Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
x) Gauge
g IO GaugeSample -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> () -> IO ()
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 (Double -> Double -> Double
forall a. Num a => a -> a -> a
subtract Double
x) Gauge
g IO GaugeSample -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> () -> IO ()
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 (Double -> Double -> Double
forall a b. a -> b -> a
const Double
x) Gauge
g IO GaugeSample -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> () -> IO ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()


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