-- | This module exports memory related services.
--
-- @since 0.1
module Pythia.Services.Memory
  ( -- * Queries
    queryMemory,

    -- * Functions
    freeMemory,
    percentageUsed,
    percentageFree,

    -- * Types
    Memory (..),
    SystemMemory (..),

    -- ** Configuration
    MemoryApp (..),
  )
where

import Data.Bytes (Bytes (MkBytes), _MkBytes)
import Pythia.Data.Percentage (Percentage (MkPercentage))
import Pythia.Data.Percentage qualified as Percentage
import Pythia.Prelude
import Pythia.Services.Memory.Free qualified as Free
import Pythia.Services.Memory.Types
  ( Memory (MkMemory),
    MemoryApp (MemoryAppFree),
    SystemMemory (MkSystemMemory, total, used),
  )

-- $setup
-- >>> import Control.Exception (displayException)
-- >>> import Pythia.Prelude

-- | Queries the memory based on the configuration.
--
-- @since 0.1
queryMemory ::
  ( MonadPathReader m,
    MonadThrow m,
    MonadTypedProcess m
  ) =>
  MemoryApp ->
  m SystemMemory
queryMemory :: forall (m :: Type -> Type).
(MonadPathReader m, MonadThrow m, MonadTypedProcess m) =>
MemoryApp -> m SystemMemory
queryMemory MemoryApp
MemoryAppFree = m SystemMemory
forall (m :: Type -> Type).
(MonadPathReader m, MonadThrow m, MonadTypedProcess m) =>
m SystemMemory
Free.memoryShellApp

-- | Returns the amount of free memory.
--
-- @since 0.1
freeMemory :: SystemMemory -> Memory
freeMemory :: SystemMemory -> Memory
freeMemory SystemMemory
sysMem = Memory
free
  where
    t :: Natural
t = SystemMemory
sysMem SystemMemory -> Optic' A_Lens NoIx SystemMemory Natural -> Natural
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. (Optic A_Lens NoIx SystemMemory SystemMemory Memory Memory
#total Optic A_Lens NoIx SystemMemory SystemMemory Memory Memory
-> Optic
     An_Iso NoIx Memory Memory (Bytes 'B Natural) (Bytes 'B Natural)
-> Optic
     A_Lens
     NoIx
     SystemMemory
     SystemMemory
     (Bytes 'B Natural)
     (Bytes 'B Natural)
forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
       b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Optic
  An_Iso NoIx Memory Memory (Bytes 'B Natural) (Bytes 'B Natural)
#unMemory Optic
  A_Lens
  NoIx
  SystemMemory
  SystemMemory
  (Bytes 'B Natural)
  (Bytes 'B Natural)
-> Optic
     An_Iso NoIx (Bytes 'B Natural) (Bytes 'B Natural) Natural Natural
-> Optic' A_Lens NoIx SystemMemory Natural
forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
       b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Optic
  An_Iso NoIx (Bytes 'B Natural) (Bytes 'B Natural) Natural Natural
forall (s :: Size) n. Iso' (Bytes s n) n
_MkBytes)
    u :: Natural
u = SystemMemory
sysMem SystemMemory -> Optic' A_Lens NoIx SystemMemory Natural -> Natural
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. (Optic A_Lens NoIx SystemMemory SystemMemory Memory Memory
#used Optic A_Lens NoIx SystemMemory SystemMemory Memory Memory
-> Optic
     An_Iso NoIx Memory Memory (Bytes 'B Natural) (Bytes 'B Natural)
-> Optic
     A_Lens
     NoIx
     SystemMemory
     SystemMemory
     (Bytes 'B Natural)
     (Bytes 'B Natural)
forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
       b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Optic
  An_Iso NoIx Memory Memory (Bytes 'B Natural) (Bytes 'B Natural)
#unMemory Optic
  A_Lens
  NoIx
  SystemMemory
  SystemMemory
  (Bytes 'B Natural)
  (Bytes 'B Natural)
-> Optic
     An_Iso NoIx (Bytes 'B Natural) (Bytes 'B Natural) Natural Natural
-> Optic' A_Lens NoIx SystemMemory Natural
forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
       b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Optic
  An_Iso NoIx (Bytes 'B Natural) (Bytes 'B Natural) Natural Natural
forall (s :: Size) n. Iso' (Bytes s n) n
_MkBytes)
    free :: Memory
free = Bytes 'B Natural -> Memory
MkMemory (Bytes 'B Natural -> Memory) -> Bytes 'B Natural -> Memory
forall a b. (a -> b) -> a -> b
$ Natural -> Bytes 'B Natural
forall (s :: Size) n. n -> Bytes s n
MkBytes (Natural -> Bytes 'B Natural) -> Natural -> Bytes 'B Natural
forall a b. (a -> b) -> a -> b
$ Natural
t Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
- Natural
u

-- | Returns the used memory as a percentage.
--
-- @since 0.1
percentageUsed :: SystemMemory -> Percentage
percentageUsed :: SystemMemory -> Percentage
percentageUsed SystemMemory
sysMem = Percentage
p
  where
    t :: Double
t = Natural -> Double
natToDouble (Natural -> Double) -> Natural -> Double
forall a b. (a -> b) -> a -> b
$ SystemMemory
sysMem SystemMemory -> Optic' A_Lens NoIx SystemMemory Natural -> Natural
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. (Optic A_Lens NoIx SystemMemory SystemMemory Memory Memory
#total Optic A_Lens NoIx SystemMemory SystemMemory Memory Memory
-> Optic
     An_Iso NoIx Memory Memory (Bytes 'B Natural) (Bytes 'B Natural)
-> Optic
     A_Lens
     NoIx
     SystemMemory
     SystemMemory
     (Bytes 'B Natural)
     (Bytes 'B Natural)
forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
       b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Optic
  An_Iso NoIx Memory Memory (Bytes 'B Natural) (Bytes 'B Natural)
#unMemory Optic
  A_Lens
  NoIx
  SystemMemory
  SystemMemory
  (Bytes 'B Natural)
  (Bytes 'B Natural)
-> Optic
     An_Iso NoIx (Bytes 'B Natural) (Bytes 'B Natural) Natural Natural
-> Optic' A_Lens NoIx SystemMemory Natural
forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
       b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Optic
  An_Iso NoIx (Bytes 'B Natural) (Bytes 'B Natural) Natural Natural
forall (s :: Size) n. Iso' (Bytes s n) n
_MkBytes)
    u :: Double
u = Natural -> Double
natToDouble (Natural -> Double) -> Natural -> Double
forall a b. (a -> b) -> a -> b
$ SystemMemory
sysMem SystemMemory -> Optic' A_Lens NoIx SystemMemory Natural -> Natural
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. (Optic A_Lens NoIx SystemMemory SystemMemory Memory Memory
#used Optic A_Lens NoIx SystemMemory SystemMemory Memory Memory
-> Optic
     An_Iso NoIx Memory Memory (Bytes 'B Natural) (Bytes 'B Natural)
-> Optic
     A_Lens
     NoIx
     SystemMemory
     SystemMemory
     (Bytes 'B Natural)
     (Bytes 'B Natural)
forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
       b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Optic
  An_Iso NoIx Memory Memory (Bytes 'B Natural) (Bytes 'B Natural)
#unMemory Optic
  A_Lens
  NoIx
  SystemMemory
  SystemMemory
  (Bytes 'B Natural)
  (Bytes 'B Natural)
-> Optic
     An_Iso NoIx (Bytes 'B Natural) (Bytes 'B Natural) Natural Natural
-> Optic' A_Lens NoIx SystemMemory Natural
forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
       b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Optic
  An_Iso NoIx (Bytes 'B Natural) (Bytes 'B Natural) Natural Natural
forall (s :: Size) n. Iso' (Bytes s n) n
_MkBytes)
    p :: Percentage
p = HasCallStack => Word8 -> Percentage
Word8 -> Percentage
Percentage.unsafePercentage (Word8 -> Percentage) -> Word8 -> Percentage
forall a b. (a -> b) -> a -> b
$ Double -> Word8
doubleToWord8 (Double -> Word8) -> Double -> Word8
forall a b. (a -> b) -> a -> b
$ Double
u Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
t

    doubleToWord8 :: Double -> Word8
    doubleToWord8 :: Double -> Word8
doubleToWord8 = Double -> Word8
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor (Double -> Word8) -> (Double -> Double) -> Double -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
100)

-- | Returns the free memory as a percentage.
--
-- @since 0.1
percentageFree :: SystemMemory -> Percentage
percentageFree :: SystemMemory -> Percentage
percentageFree SystemMemory
sysMem = HasCallStack => Word8 -> Percentage
Word8 -> Percentage
Percentage.unsafePercentage (Word8
100 Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
usedPercent)
  where
    (MkPercentage Word8
usedPercent) = SystemMemory -> Percentage
percentageUsed SystemMemory
sysMem