import qualified Data.Map as M
import Data.Monoid
import System.Exit
import XMonad hiding ((|||))
import XMonad.Actions.MouseResize
import XMonad.Hooks.EwmhDesktops
import XMonad.Hooks.InsertPosition (Focus (Newer), Position (Below, Master), insertPosition)
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.ManageHelpers (doCenterFloat, doFullFloat, isDialog, isFullscreen)
import XMonad.Layout.Fullscreen
import XMonad.Layout.LayoutCombinators
import XMonad.Layout.LimitWindows
import XMonad.Layout.MultiToggle
import XMonad.Layout.MultiToggle.Instances
import XMonad.Layout.NoBorders
import XMonad.Layout.NoFrillsDecoration (simpleDeco)
import XMonad.Layout.Reflect (reflectHoriz)
import XMonad.Layout.Renamed
import XMonad.Layout.ResizableTile
import XMonad.Layout.SimpleDecoration
import XMonad.Layout.Simplest
import XMonad.Layout.SimplestFloat
import XMonad.Layout.Spacing
import XMonad.Layout.SubLayouts
import XMonad.Layout.Tabbed
import XMonad.Layout.ToggleLayouts
import qualified XMonad.Layout.ToggleLayouts as T (ToggleLayout (Toggle), toggleLayouts)
import XMonad.Layout.WindowArranger
import XMonad.Layout.WindowNavigation
import qualified XMonad.StackSet as W
import XMonad.Util.EZConfig (additionalKeysP, checkKeymap)
import XMonad.Util.SpawnOnce

myTerminal = "alacritty"

myFocusFollowsMouse = True

-- mod1Mask = left alt; mod3Mask = right alt; mod4Mask = windows key
myModMask = mod4Mask

myWorkspaces = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]

myWorkspaceKeys = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]

myBorderWidth = 2

myNormalBorderColor = "#dddddd"

myFocusedBorderColor = "#f0c674"

myAddKeys =
  [ ("M-S-r", spawn "xmonad --recompile && xmonad --restart && notify-send 'Xmonad restarted'"),
    ("M-h", sendMessage Shrink), -- Shrink master area
    ("M-l", sendMessage Expand), -- Expand master area
    ("M-,", sendMessage (IncMasterN 1)), -- Increment the number of windows in the master area
    ("M-.", sendMessage (IncMasterN (-1))), -- Deincrement the number of windows in the master area
    -- ("M-t", withFocused $ windows . W.sink), -- Push window back into tiling
    ("M-x", kill),
    ("M-q", kill),
    ("M-C-j", sendMessage $ JumpToLayout "TiledBottom"),
    ("M-C-k", sendMessage $ JumpToLayout "TiledTop"),
    ("M-C-h", sendMessage $ JumpToLayout "TiledLeft"),
    ("M-C-l", sendMessage $ JumpToLayout "TiledRight"),
    ("M-f", sendMessage $ T.Toggle "Full"),
    -- ("M-S-<Space>", setLayout $ XMonad.layoutHook conf), --  Reset the layouts on the current workspace to default
    ("M-n", refresh), -- Resize viewed windows to the correct size
    ("M-<Tab>", windows W.focusDown), -- Move focus to the next window
    ("M-j", windows W.focusDown), -- Move focus to the next window
    ("M-k", windows W.focusUp), -- Move focus to the previous window
    ("M-m", windows W.focusMaster), -- Move focus to the master window
    -- Swap the focused window and the master window
    -- ((modm, xK_Return), windows W.swapMaster),
    ("M-S-j", windows W.swapDown), -- Swap the focused window with the next window
    ("M-S-k", windows W.swapUp), -- Swap the focused window with the previous window
    ("M-S-e", spawn "~/.xmonad/scripts/dzen_exit_menu.pl"),
    -- My keybound programs
    ("M-d", spawn "rofi -show run #dmenu_recency -i"),
    ("M-<Return>", spawn myTerminal),
    ("M-b", spawn "firefox"),
    ("M-t", spawn "krusader"),
    ("M-u", spawn "pamac-manager"),
    ("M-c", spawn "qalculate-gtk"),
    ("<XF86AudioMute>", spawn "amixer set Master toggle"),
    ("<XF86AudioLowerVolume>", spawn "amixer set Master 10%- unmute"),
    ("<XF86AudioRaiseVolume>", spawn "amixer set Master 10%+ unmute")
  ]
    -- Switch to workspace
    ++ [ ("M-" ++ key, windows $ W.greedyView workspace)
         | (key, workspace) <- zip myWorkspaceKeys myWorkspaces
       ]
    -- Move window to workspace and follow
    ++ [ ( "M-S-" ++ key,
           do
             windows $ W.shift workspace
             windows $
               W.greedyView workspace
         )
         | (key, workspace) <- zip myWorkspaceKeys myWorkspaces
       ]
    -- Move window to workspace
    ++ [ ("M-C-" ++ key, windows $ W.shift workspace)
         | (key, workspace) <- zip myWorkspaceKeys myWorkspaces
       ]

myKeys conf@(XConfig {XMonad.modMask = modm}) =
  M.fromList $
    [ --  Reset the layouts on the current workspace to default
      ((modm .|. shiftMask, xK_space), setLayout $ XMonad.layoutHook conf),
      -- Quit xmonad
      ((modm .|. shiftMask, xK_q), io exitSuccess)
    ]

myMouseBindings (XConfig {XMonad.modMask = modm}) =
  M.fromList
    -- mod-button1, Set the window to floating mode and move by dragging
    [ ( (modm, button1),
        \w ->
          focus w >> mouseMoveWindow w
            >> windows W.shiftMaster
      ),
      -- mod-button2, Raise the window to the top of the stack
      ((modm, button2), \w -> focus w >> windows W.shiftMaster),
      -- mod-button3, Set the window to floating mode and resize by dragging
      ( (modm, button3),
        \w ->
          focus w >> mouseResizeWindow w
            >> windows W.shiftMaster
      )
      -- you may also bind events to the mouse scroll wheel (button4 and button5)
    ]

myLayouts = T.toggleLayouts Full $ tiledRight ||| tiledBottom ||| tiledLeft ||| tiledTop ||| Full
  where
    tiledRight = renamed [Replace "TiledRight"] $ Tall nmaster delta ratio
    tiledBottom = renamed [Replace "TiledBottom"] $ Mirror $ Tall nmaster delta ratio
    tiledLeft = renamed [Replace "TiledLeft"] $ reflectHoriz $ Tall nmaster delta ratio
    tiledTop = renamed [Replace "TiledTop"] $ Mirror $ reflectHoriz $ Tall nmaster delta ratio

    -- The default number of windows in the master pane
    nmaster = 1
    -- Default proportion of screen occupied by master pane
    ratio = 1 / 2
    -- Percent of screen to increment by when resizing panes
    delta = 3 / 100

-- To match on the WM_NAME, you can use 'title' in the same way that
-- 'className' and 'resource' are used below.
myManageHook =
  composeAll
    [ className =? "Qalculate-gtk" --> doCenterFloat,
      resource =? "desktop_window" --> doIgnore,
      resource =? "kdesktop" --> doIgnore,
      className =? "firefox" <&&> title =? "Mozilla Firefox" --> doShift "1" <+> doF (W.greedyView "1"),
      className =? "TelegramDesktop" --> doShift "9",
      className =? "Signal" --> doShift "9",
      className =? "Rocket.Chat" --> doShift "9",
      className =? "Element" --> doShift "9",
      className =? "Thunderbird" --> doShift "10",
      className =? "zoom" --> doShift "5"
      -- isFullscreen --> doFullFloat
    ]

myStartupHook = do
  spawn "~/.config/polybar/startup.sh"
  spawnOnce "picom"
  spawnOnce "nm-applet"
  spawnOnce "blueman-applet"
  spawnOnce "xfce4-power-manager"
  spawnOnce "/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1"
  spawnOnce "start-pulseaudio-x11"
  spawnOnce "feh --bg-fill ~/Bilder/background.jpg"
  spawnOnce "/usr/lib/xfce4/notifyd/xfce4-notifyd"
  spawnOnce "jgmenu --at-pointer --hide-on-startup"

  -- Very important return()!!!
  return () >> checkKeymap myConfig myAddKeys

main =
  xmonad $
    ewmhFullscreen $ ewmh $ docks myConfig

myConfig =
  def
    { terminal = myTerminal,
      focusFollowsMouse = myFocusFollowsMouse,
      borderWidth = myBorderWidth,
      modMask = myModMask,
      workspaces = myWorkspaces,
      normalBorderColor = myNormalBorderColor,
      focusedBorderColor = myFocusedBorderColor,
      -- key bindings
      keys = myKeys,
      mouseBindings = myMouseBindings,
      -- hooks, layouts
      layoutHook = smartBorders $ avoidStruts $ smartSpacingWithEdge 2 $ myLayouts,
      manageHook = insertPosition Below Newer <+> myManageHook,
      -- handleEventHook =
      -- logHook =
      startupHook = myStartupHook
    }
    `additionalKeysP` myAddKeys

-- Local Variables:
-- lsp-lens-enable: nil
-- End: