import XMonad
import XMonad.Hooks.DynamicLog
import XMonad.Hooks.ManageDocks
import XMonad.Util.Run(spawnPipe)
import XMonad.Util.EZConfig(additionalKeys)
import System.IO
import qualified Data.Map as M
import XMonad.Actions.CycleWS
import XMonad.Actions.CycleRecentWS
import XMonad.Hooks.DynamicLog   (PP(..), dynamicLogWithPP, wrap, defaultPP)
import XMonad.Hooks.UrgencyHook

-- keybindings: similar to the awesome default config i got used to
-- ---------------------------------------------------------------------------

myKeys conf@(XConfig {XMonad.modMask = modm}) = [
	((modm, xK_Down), nextScreen),
	((modm .|. shiftMask, xK_Down), shiftNextScreen),
	((modm, xK_Up), prevScreen),
	((modm .|. shiftMask, xK_Up), shiftPrevScreen),

	((modm, xK_Left), prevWS),
	((modm .|. shiftMask, xK_Left), shiftToPrev),
	((modm, xK_Right), nextWS),
	((modm .|. shiftMask, xK_Right), shiftToNext),

	((modm, xK_Escape), toggleWS),

	((modm .|. shiftMask, xK_b), spawn "epiphany -p")
	]
newKeys x  = M.union (keys defaultConfig x) (M.fromList (myKeys x))

-- main program
-- ---------------------------------------------------------------------------

main = do
	statusBarPipe <- spawnPipe statusBarCmd
	xmonad $ withUrgencyHook dzenUrgencyHook { args = ["-bg", "darkgreen", "-xs", "1"] }
		$ defaultConfig {
		modMask = mod4Mask, -- windows key
		terminal = "uxterm",
		manageHook = manageDocks <+> manageHook defaultConfig, -- autodetection for gnome panel and similar
		layoutHook = avoidStruts  $  layoutHook defaultConfig, -- adds gaps for panels
		keys = newKeys,
		logHook = dynamicLogWithPP $ myPP statusBarPipe
	}

-- status bar on top
-- ---------------------------------------------------------------------------

statusBarCmd= "dzen2 -p -h 16 -ta l -bg '" ++ myNormalBGColor ++ "' -fg '" ++ myNormalFGColor ++ "'"

-- helper function (my first haskell function *g*)
--
-- as ppUrgent is applied after ppHidden, the dzen markup has to be removed and new stuff added

dzenStripWrap :: String -> String -> String -> String
dzenStripWrap _ _ "" = ""
dzenStripWrap l r m = l ++ dzenStrip m ++ r

-- status bar design
--
-- based on http://www.haskell.org/haskellwiki/Xmonad/Config_archive/Xilon's_xmonad.hs

myNormalBGColor     = "#2e3436"
myNormalFGColor     = "#babdb6"
myEmptyBGColor      = myNormalBGColor
myEmptyFGColor      = "#7478f6" -- (myNormalBGColor + myNormalFGColor) / 2

myFocusedBGColor    = "#414141"
myFocusedFGColor    = "#73d216"
myOtherscreenBGColor= myFocusedBGColor
myOtherscreenFGColor= myNormalFGColor
mySeperatorColor    = "#000000"
myUrgentBGColor     = "#0000ff"
myUrgentFGColor     = "#f57900"


-- pretty printer

myPP handle = defaultPP {
        ppCurrent             	= wrap ("^fg(" ++ myFocusedFGColor ++ ")^bg(" ++ myFocusedBGColor ++ ")^p(4)") "^p(4)^fg()^bg()",
        ppUrgent                = dzenStripWrap ("^fg(" ++ myUrgentFGColor  ++ ")^bg(" ++ myUrgentBGColor  ++ ")^p(4)") ("^fg(" ++ myUrgentFGColor  ++ ")^bg(" ++ myUrgentBGColor  ++ ")^p(4)^fg()^bg()"),
        ppVisible               = wrap ("^fg(" ++ myOtherscreenFGColor  ++ ")^bg(" ++ myOtherscreenBGColor  ++ ")^p(4)") "^p(4)^fg()^bg()",
        ppHidden                = wrap ("^fg(" ++ myNormalFGColor  ++ ")^bg(" ++ myNormalBGColor  ++ ")^p(4)") "^p(4)^fg()^bg()",
        ppHiddenNoWindows       = wrap ("^fg(" ++ myEmptyFGColor  ++ ")^bg(" ++ myEmptyBGColor  ++ ")^p(4)") "^p(4)^fg()^bg()",
        ppWsSep     = "", -- explicit ^p(4) above provide coloured border
        ppSep     = "^fg(" ++ mySeperatorColor ++ ") * ^fg()",
        ppLayout = (\x -> ""), -- i usually see which layout is used and don't need an extra display
        ppTitle   = wrap ("^fg(" ++ myFocusedFGColor ++ ")") "^fg()" ,
        ppOutput  = hPutStrLn handle
}
