------------------------------------------------------------------------------
-- |
-- Module      :  Dzen
-- Copyright   :  (c) Mads N Noe 2009
-- Maintainer  :  mntnoe (@) gmail.com
-- License     :  as-is
--
-- Functions for spawning dzen instances.
--
------------------------------------------------------------------------------

module Dzen (
    spawnDzenWithPipe,
    spawnDzenWithConky,
    dzen
    ) where

-- Haskell modules
import Control.Monad
import Data.List
import Foreign.C.Types (CInt)
import GHC.IOBase (Handle)
import System.Cmd
import System.Environment (getEnv)
import System.Posix.Files(fileExist)

-- XMonad modules
import Control.Monad
import Graphics.X11.Xlib.Display
import XMonad (spawn)
import XMonad.Prompt
import XMonad.Util.Run(spawnPipe)

-- My modules
import Util (Host (Desktop, Laptop))

-- | Spawn two dzen instances at the top of the screen, reading input
--   from xmonad and hbar respectively.
spawnDzenWithPipe :: Host -> XPConfig -> IO Handle
spawnDzenWithPipe host xpc = do
    (sw, sh) <- getScreenDim
    let w = 300
    system $ hbar host ++ dzen xpc
        Nothing  -- put dzen at the top of the screen
        (sw - w) -- horizontal position
        w        -- horizontal width
        'r'      -- text align
        actions ++ " &"
    spawnPipe $ dzen xpc
        Nothing  -- put dzen at the top of the screen
        0        -- horizontal position
        (sw - w) -- horizontal width
        'l'      -- text align
        actions

  where    
    -- Show battery info only on the laptop.
    hbar Desktop = "hbar -cmt | "
    hbar Laptop = "hbar -cmbt | "

    -- Mouse clicking cycles between populated workspaces.  xmcli is my
    -- ServerMode client.
    actions = "button3=exec:xmcli 2;button1=exec:xmcli 3"

-- | Spawn a dzen instance at the bottom of the screen using conky for input.
spawnDzenWithConky ::  XPConfig -> FilePath -> IO ()
spawnDzenWithConky xpc conkyrc = do
    (sw, sh) <- getScreenDim
    let dest = dzen xpc
            (Just sh) -- put dzen at the bottom of the screen
            0         -- horizontal position
            sw        -- horizontal width
            'c'       -- text align
            ""        -- no actions
    fileExist conkyrc >>= (flip when $ do_ $ system $ dzenWithConky conkyrc dest)

  where
    do_ x = x >> return ()

    dzenWithConky conkyrc dest = intercalate " " ["conky-cli -c", conkyrc, "|", dest, "&"]

-- | Return a string that launches dzen with the given configuration.
dzen :: Num a => XPConfig -- ^ prompt style configuration
              -> Maybe a  -- ^ Nothing: put dzen at the top of the screen
                          --   Just h:  put dzen at the bottom of the screen with height h
              -> a        -- ^ horizontal position
              -> a        -- ^ horizontal width
              -> Char     -- ^ text align
              -> String   -- ^ actions
              -> String
dzen xpc mh x w ta e =
    let y = case mh of
            Nothing -> 0
            Just h  -> h - (fromInteger $ toInteger $ height xpc) in
        intercalate " "
            [ "dzen2"
            , "-x"  , show x
            , "-w"  , show w
            , "-y"  , show y
            , "-h"  , show  $ height  xpc
            , "-fn" , quote $ font    xpc
            , "-bg" , quote $ bgColor xpc
            , "-fg" , quote $ fgColor xpc
            , "-ta" , [ta]
            , "-e"  , quote e
            ]
    where
        quote x = "'" ++ x ++ "'"

-- | Return the dimensions of the (primary?) screen.
getScreenDim :: IO (CInt, CInt)
getScreenDim = do
    d <- openDisplay ""
    let s = defaultScreen d
        w = displayWidth d s
        h = displayHeight d s
    closeDisplay d
    return (w, h)