module System.Taffybar.Information.Memory (
  MemoryInfo(..),
  parseMeminfo
  ) where

toMB :: String -> Double
toMB size = (read size :: Double) / 1024

data MemoryInfo = MemoryInfo
  { memoryTotal :: Double
  , memoryFree :: Double
  , memoryBuffer :: Double
  , memoryCache :: Double
  , memorySwapTotal :: Double
  , memorySwapFree :: Double
  , memorySwapUsed :: Double -- swapTotal - swapFree
  , memorySwapUsedRatio :: Double -- swapUsed / swapTotal
  , memoryAvailable :: Double -- An estimate of how much memory is available
  , memoryRest :: Double -- free + buffer + cache
  , memoryUsed :: Double -- total - rest
  , memoryUsedRatio :: Double -- used / total
  }

emptyMemoryInfo :: MemoryInfo
emptyMemoryInfo = MemoryInfo 0 0 0 0 0 0 0 0 0 0 0 0

parseLines :: [String] -> MemoryInfo -> MemoryInfo
parseLines (line:rest) memInfo = parseLines rest newMemInfo
  where newMemInfo = case words line of
                       (label:size:_) ->
                         case label of
                           "MemTotal:"     -> memInfo { memoryTotal = toMB size }
                           "MemFree:"      -> memInfo { memoryFree = toMB size }
                           "MemAvailable:" -> memInfo { memoryAvailable = toMB size }
                           "Buffers:"      -> memInfo { memoryBuffer = toMB size }
                           "Cached:"       -> memInfo { memoryCache = toMB size }
                           "SwapTotal:"    -> memInfo { memorySwapTotal = toMB size }
                           "SwapFree:"     -> memInfo { memorySwapFree = toMB size }
                           _               -> memInfo
                       _ -> memInfo
parseLines _ memInfo = memInfo

parseMeminfo :: IO MemoryInfo
parseMeminfo = do
  s <- readFile "/proc/meminfo"
  let m = parseLines (lines s) emptyMemoryInfo
      rest = memoryFree m + memoryBuffer m + memoryCache m
      used = memoryTotal m - rest
      usedRatio = used / memoryTotal m
      swapUsed = memorySwapTotal m - memorySwapFree m
      swapUsedRatio = swapUsed / memorySwapTotal m
  return m { memoryRest = rest
           , memoryUsed = used
           , memoryUsedRatio = usedRatio
           , memorySwapUsed = swapUsed
           , memorySwapUsedRatio = swapUsedRatio
           }
