{-# OPTIONS_GHC -fno-cse #-}


{-| Obtain a MAC address for the host system, on *NIX and Windows.
 -}


module System.Info.MAC
  ( mac
  , macs
  , nic
  , nics
  , refresh
  ) where

import Data.MAC
import System.Info.MAC.Fetch

import Data.IORef
import System.IO
import System.IO.Unsafe
import Data.Maybe
import Control.Applicative


{-| Fetch MAC address, using a cached value if it is available.
 -}
mac                         ::  IO (Maybe MAC)
mac :: IO (Maybe MAC)
mac                          =  [MAC] -> Maybe MAC
forall a. [a] -> Maybe a
listToMaybe ([MAC] -> Maybe MAC) -> IO [MAC] -> IO (Maybe MAC)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO [MAC]
macs


{-| Fetch MAC addresses, using a cached value if it is available.
 -}
macs                        ::  IO [MAC]
macs :: IO [MAC]
macs                         =  ((String, MAC) -> MAC) -> [(String, MAC)] -> [MAC]
forall a b. (a -> b) -> [a] -> [b]
map (String, MAC) -> MAC
forall a b. (a, b) -> b
snd ([(String, MAC)] -> [MAC]) -> IO [(String, MAC)] -> IO [MAC]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO [(String, MAC)]
nics


{-| Fetch a name-MAC pair, using a cached value if it is available.
 -}
nic                         ::  IO (Maybe (String, MAC))
nic :: IO (Maybe (String, MAC))
nic                          =  [(String, MAC)] -> Maybe (String, MAC)
forall a. [a] -> Maybe a
listToMaybe ([(String, MAC)] -> Maybe (String, MAC))
-> IO [(String, MAC)] -> IO (Maybe (String, MAC))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO [(String, MAC)]
nics


{-| Fetch name-MAC pairs, using a cached value if it is available.
 -}
nics                        ::  IO [(String, MAC)]
nics :: IO [(String, MAC)]
nics                         =  do
  [(String, MAC)]
val                       <-  IORef [(String, MAC)] -> IO [(String, MAC)]
forall a. IORef a -> IO a
readIORef IORef [(String, MAC)]
forall a. IORef [a]
fetched
  case [(String, MAC)]
val of [ ]           ->  IO [(String, MAC)]
refresh
              _:_           ->  [(String, MAC)] -> IO [(String, MAC)]
forall (m :: * -> *) a. Monad m => a -> m a
return [(String, MAC)]
val


{-| Explicitly re-run the MAC reading operation.
 -}
refresh                     ::  IO [(String, MAC)]
refresh :: IO [(String, MAC)]
refresh                      =  do
  [(String, MAC)]
res                       <-  IO [(String, MAC)]
fetchNICs
  IORef [(String, MAC)] -> [(String, MAC)] -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef [(String, MAC)]
forall a. IORef [a]
fetched [(String, MAC)]
res
  [(String, MAC)] -> IO [(String, MAC)]
forall (m :: * -> *) a. Monad m => a -> m a
return [(String, MAC)]
res


{-# NOINLINE fetched #-}
fetched :: IORef [a]
fetched                      =  IO (IORef [a]) -> IORef [a]
forall a. IO a -> a
unsafePerformIO (IO (IORef [a]) -> IORef [a]) -> IO (IORef [a]) -> IORef [a]
forall a b. (a -> b) -> a -> b
$ [a] -> IO (IORef [a])
forall a. a -> IO (IORef a)
newIORef []