    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 for starting new apps
      , 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 (label:size:_) = words line
            newMemInfo = 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
    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
               }