content: {-
      Copyright 2016 Markus Ongyerth
  
      This file is part of Monky.
  
      Monky is free software: you can redistribute it and/or modify
      it under the terms of the GNU Lesser General Public License as published by
      the Free Software Foundation, either version 3 of the License, or
      (at your option) any later version.
  
      Monky is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU Lesser General Public License for more details.
  
      You should have received a copy of the GNU Lesser General Public License
      along with Monky.  If not, see <http://www.gnu.org/licenses/>.
  -}
  {-|
  Module      : Monky.Examples.Wifi.Event
  Description : The event based wifi module interface
  Maintainer  : ongy
  Stability   : experimental
  Portability : Linux
  
  This module provides the event based interface to wifi information.
  It is rather limited because of some technical stuff with 802.11.
  If you need more information about your wifi use the "Monky.Exmaple.Wifi.Poll" module.
  -}
  {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE ScopedTypeVariables #-}
  {-# LANGUAGE CPP #-}
  module Monky.Examples.Wifi.Event
    ( getWifiHandle
    , getWifiHandle'
  
    , guessWifiHandle
    , guessWifiHandle'
  
    , getTextify
  
    , WifiEvtHandle
    , WifiFormat(..)
    )
  where
  
  import Formatting
  import Data.Text (Text)
  import qualified Data.Text as T
  import Data.Maybe (fromMaybe)
  
  import Monky.Modules
  import Monky.Examples.Utility
  import Monky.Wifi
  
  #if MIN_VERSION_base(4,8,0)
  #else
  import Control.Applicative ((<$>), pure)
  #endif
  
  -- Socket Interface Conversion Offline
  -- |The handle type for this module
  data WifiEvtHandle = WH SSIDSocket Interface (WifiStats -> Text) Text
  
  -- NOTE: If you extend this, also extend the type in Monky.Examples.Wifi.Poll
  -- |A typesafe version of a format string
  data WifiFormat
    = FormatChannel -- ^Print the current networks channel
    | FormatName -- ^Print the ESSID of the current network, may look weird because SSIDs are
    | FormatFreq -- ^Print the frequency the current network sends on (related to channel)
    | FormatText Text -- ^Print a plaintext string
  
  -- | Apply the 'WifiFormat' to show some 'WifiStats' information as text.
  getTextify :: WifiFormat -> WifiStats -> Text
  getTextify FormatChannel    = sformat int . wifiChannel
  getTextify FormatName       = T.pack . wifiName
  getTextify FormatFreq       = sformat int . wifiFreq
  getTextify (FormatText str) = const str
  
  getFunction :: [WifiFormat] -> WifiStats -> Text
  getFunction xs = T.concat . (\a -> map (($ a) . getTextify) xs)
  
  -- |Get a wifi handle
  getWifiHandle
    :: [WifiFormat] -- ^Format "String" for output generation
    -> Text -- ^Text that should be displayed when wifi is disconnected
    -> String -- ^Name of the interface
    -> IO WifiEvtHandle
  getWifiHandle f d n =
    getWifiHandle' (getFunction f) d n
  
  -- | Lower level version of 'getWifiHandle' if you need exted information.
  getWifiHandle'
      :: (WifiStats -> Text)
      -> Text
      -> String
      -> IO WifiEvtHandle
  getWifiHandle' f d n = do
      s <- getSSIDSocket
      i <- fromMaybe (error ("Could not find interface: " ++ n)) <$> getInterface s n
      return (WH s i f d)
  
  -- | Lower level version of 'guessWifiHandle' for more control
  guessWifiHandle'
      :: (WifiStats -> Text)
      -> Text -- ^Text that should be displayed when wifi is disconnected
      -> IO WifiEvtHandle
  guessWifiHandle' f d = do
      s <- getSSIDSocket
      i <- fromMaybe (error "Couldn't find any NL80211 interface") <$> guessInterface s
      return (WH s i f d)
  
  {- | Get a wifi handle, guess the interface
  
  Guess isn't quite the right word here. This asks the NL80211 subsystem for a
  list of devices and picks the first one.
  -}
  guessWifiHandle
      :: [WifiFormat] -- ^Format "String" for output generation
      -> Text -- ^Text that should be displayed when wifi is disconnected
      -> IO WifiEvtHandle
  guessWifiHandle f d =
      guessWifiHandle' (getFunction f) d
  
  getEventOutput :: WifiEvtHandle -> IO [MonkyOut]
  getEventOutput (WH s i f d) = do
    new <- gotReadable s i
    case new of
      (WifiConnect x) -> do
          return [MonkyPlain $ f x]
      WifiNone -> return []
      WifiDisconnect -> return [MonkyPlain d]
  
  instance EvtModule WifiEvtHandle where
    startEvtLoop h@(WH s i f d) r = do
      ret <- getCurrentWifiStats s i
      r . pure $ case ret of
              Nothing -> MonkyPlain d
              Just x -> MonkyPlain $ f x
      prepareEvents s
      loopFd h (getWifiFd s) r getEventOutput
  