from libqtile.config import Key, Screen, Group, Drag, Click, Match
from libqtile.command import lazy
from libqtile import layout, bar, widget, hook
import logging
import os
import re
import subprocess
from libqtile.log_utils import logger
# import psutil
# import getpass

mod = "mod4"
alt = "mod1"

home = os.path.expanduser("~")
hostname = os.uname().nodename
display = os.environ['DISPLAY']
terminal = "termite"
drun_launcher = "rofi -show drun"
run_launcher = "rofi -show run"
lock = home+"/bin/xorg_lock"
brightness_step = "2"
brightness_up = "backlight -i "+brightness_step
brightness_down = "backlight -i -"+brightness_step
volume_up = home+"/bin/set_volume increase"
volume_down = home+"/bin/set_volume decrease"
volume_toggle = home+"/bin/set_volume toggle"
audio_prev = home+"/bin/notify_mpd prev"
audio_next = home+"/bin/notify_mpd next"
audio_toggle = home+"/bin/notify_mpd toggle"
audio_stop = home+"/bin/notify_mpd stop"
conky_network = ['/usr/bin/conky',
                 '-X',
                 display,
                 '-c',
                 home+'/.config/conky/'+hostname+'-network.conf']
conky_general = ['/usr/bin/conky',
                 '-X',
                 display,
                 '-c',
                 home+'/.config/conky/'+hostname+'-general.conf']
background = ['feh',
              '--randomize',
              '--recursive',
              '--bg-fill',
              home+'/cloud/photos/desktop/']
compton = ['/usr/bin/compton',
           '-CGb',
           '-d',
           display]

colors = {
    "grey": "#555555",
    "red": "#DD1144",
    "blue": "#445588",
    "lgrey": "#b8b6b1",
    "green": "#008080",
}


# kick a window to another screen (handy during presentations)
def move_to_other_screen(qtile, direction=1):
    other_scr_index = (qtile.screens.index(qtile.currentScreen) + direction) \
            % len(qtile.screens)
    othergroup = None
    for group in qtile.cmd_groups().values():
        if group['screen'] == other_scr_index:
            othergroup = group['name']
            break
    if othergroup:
        qtile.moveToGroup(othergroup)


keys = [
    # base commands
    # restart qtile
    Key([mod, "control"], "r", lazy.restart()),
    # close qtile
    Key([mod, "control"], "q", lazy.shutdown()),
    # start run launcher
    Key([mod], "r", lazy.spawn(run_launcher)),
    # start drun launcher
    Key([mod], "p", lazy.spawn(drun_launcher)),
    # lock screen
    Key([mod, "control"], "s", lazy.spawn(lock)),
    # launch terminal
    Key([mod], "Return", lazy.spawn(terminal)),

    # multimedia
    Key([], "XF86AudioRaiseVolume", lazy.spawn(volume_up)),
    Key([], "XF86AudioLowerVolume", lazy.spawn(volume_down)),
    Key([], "XF86AudioMute", lazy.spawn(volume_toggle)),
    Key([], "XF86AudioPrev", lazy.spawn(audio_prev)),
    Key([], "XF86AudioNext", lazy.spawn(audio_next)),
    Key([], "XF86AudioPlay", lazy.spawn(audio_toggle)),
    Key([], "XF86AudioStop", lazy.spawn(audio_stop)),
    # brightness settings
    Key([], "XF86MonBrightnessUp", lazy.spawn(brightness_up)),
    Key([], "XF86MonBrightnessDown", lazy.spawn(brightness_down)),

    # cycle to previous and next group
    Key(["control", alt], "Left", lazy.screen.prev_group(skip_managed=True)),
    Key(["control", alt], "Right", lazy.screen.next_group(skip_managed=True)),
    Key(["control", mod, alt], "Left", lazy.screen.prev_group()),
    Key(["control", mod, alt], "Right", lazy.screen.next_group()),

    # Switch between windows in current stack pane
    Key([mod], "comma", lazy.layout.up()),
    Key([mod], "period", lazy.layout.down()),
    Key([mod], "Tab", lazy.layout.previous()),
    Key([mod, "shift"], "Tab", lazy.layout.next()),

    # toggle between different layouts
    Key([mod], "space", lazy.next_layout()),
    # close window
    Key([mod], "q", lazy.window.kill()),
    # toggle fullscreen
    Key([mod, "control"], "f", lazy.window.toggle_fullscreen()),
    # toggle maximized
    Key([mod], "m", lazy.window.toggle_maximize()),
    # toggle floating
    Key([mod], "f", lazy.window.toggle_floating()),
    Key([mod, alt], "space", lazy.layout.rotate()),   # flip sides

    # Multihead magic
    Key([mod, "control"], "comma", lazy.prev_screen()),
    Key([mod, "control"], "period", lazy.next_screen()),
    Key([mod], "o", lazy.function(move_to_other_screen)),

    # columns layout
    # move selection around in current group
    Key([mod], "j", lazy.layout.down()),
    Key([mod], "k", lazy.layout.up()),
    Key([mod], "h", lazy.layout.left()),
    Key([mod], "l", lazy.layout.right()),
    # move current window around in the current layout
    Key([mod, "shift"], "j", lazy.layout.shuffle_down()),
    Key([mod, "shift"], "k", lazy.layout.shuffle_up()),
    Key([mod, "shift"], "h", lazy.layout.shuffle_left()),
    Key([mod, "shift"], "l", lazy.layout.shuffle_right()),
    # grow current window into some direction
    Key([mod, "control"], "j", lazy.layout.grow_down()),
    Key([mod, "control"], "k", lazy.layout.grow_up()),
    Key([mod, "control"], "h", lazy.layout.grow_left()),
    Key([mod, "control"], "l", lazy.layout.grow_right()),
    # toggle current window to be splitting current group in half
    Key([mod], "s", lazy.layout.toggle_split()),
    # normalize the layout
    Key([mod], "n", lazy.layout.normalize()),
]

matchers = {
    'web': [
        Match(wm_class=[
            re.compile('Chromium$'),
            re.compile('Firefox$'),
            re.compile('.*qutebrowser$'),
            re.compile('TorLauncher'),
            re.compile('Tor Browser'),
        ]),
    ],
    'dev': [
        Match(wm_class=[
            re.compile('Processing'),
            re.compile('processing-app-Base'),
        ]),
        Match(title=[
            re.compile("SuperCollider\sIDE$"),
            re.compile("^SuperCollider"),
            re.compile("^Loading"),
            re.compile("Pd$"),
        ]),
    ],
    'games': [
        Match(wm_class=[
            re.compile('Minecraft'),
            re.compile('Minetest'),
            re.compile('MediaElch'),
            "pyrogenesis",
            "spring",
            "angband",
            "scummvm",
            "widelands",
        ]),
        Match(title=[
            re.compile('ScummVM'),
            re.compile('Widelands'),
            re.compile('Minecraft'),
            re.compile('Minetest'),
            "OpenRA",
            "0 A.D.",
            "Angband",
            "Alien Arena",
        ]),
    ],
    'audio': [
        Match(wm_class=[
            re.compile('Ardour'),
            re.compile('Audacity'),
            re.compile('Calfjackhost'),
            re.compile('Carla'),
            re.compile('Cadence'),
            re.compile('Ffado-mixer'),
            re.compile('Guitarix'),
            re.compile('Session Setup'),
        ]),
        Match(title=[
            re.compile('^JACK'),
            re.compile("^Calf\sJACK\sHost"),
            re.compile("^Patchage"),
            re.compile("^Instrument Tuner"),
        ]),
    ],
    'spat': [
        Match(title=[
            re.compile('.*Renderer'),
            re.compile('Controls'),
        ]),
    ],
    'photo': [
        Match(wm_class=[
            re.compile('Shotwell'),
            re.compile('Gimp'),
            re.compile('Inkscape'),
            re.compile('Darktable'),
            re.compile('Converseen'),
            re.compile('Ufraw'),
        ])
    ],
    'office': [
        Match(wm_class=[
            re.compile('Scribus'),
        ]),
        Match(title=[
            re.compile('^calibre'),
            re.compile('^JabRef'),
            re.compile("Libreoffice\sWriter$"),
        ]),
    ],
    'admin': [
        Match(wm_class=[
            re.compile('virt-manager'),
            re.compile('Virt-manager'),
        ]),
    ],
}

workspaces = [
    {"key": "1", "name": "shell"},
    {"key": "2", "name": "web", "matches": matchers["web"]},
    {"key": "3", "name": "dev", "matches": matchers["dev"]},
    {"key": "4", "name": "games", "matches": matchers["games"]},
    {"key": "5", "name": "audio", "matches": matchers["audio"]},
    {"key": "6", "name": "spat", "matches": matchers["spat"]},
    {"key": "7", "name": "photo", "matches": matchers["photo"]},
    {"key": "8", "name": "office", "matches": matchers["office"]},
    {"key": "9", "name": "admin", "matches": matchers["admin"]},
    {"key": "0", "name": "0"},
]

groups = []
for workspace in workspaces:
    matches = workspace["matches"] if "matches" in workspace else None
    groups.append(Group(workspace["name"], matches=matches))
    keys.append(
        Key([mod], workspace["key"], lazy.group[workspace["name"]].toscreen())
    )
    keys.append(Key(
        [mod, alt], workspace["key"],
        lazy.window.togroup(workspace["name"]),
    ))

layouts = [
    layout.Columns(
        border_focus=colors["red"][1:],
        border_normal=colors["green"][1:],
        margin=1,
    ),
    layout.TreeTab(
        active_bg=colors["red"][1:],
        # active_fg=colors["grey"][1:],
        active_fg='ffffff',
        inactive_bg=colors["green"][1:],
        # inactive_fg=colors["lgrey"][1:],
        inactive_fg='ffffff',
        border_focus=colors["red"][1:],
        border_normal=colors["green"][1:],
        font='Monospace',
        fontsize=14,
        margin_left=0,
        padding_left=0,
        panel_width=100,
        previous_on_rm=True,
    ),
    layout.Max(),
    layout.VerticalTile(
        border_focus=colors["red"][1:],
        border_normal=colors["green"][1:],
        margin=1,
    ),
]

widget_defaults = dict(
    font='Monospace',
    fontsize=11,
    padding=3,
)

screens = [
    Screen(
        top=bar.Bar([
            widget.CurrentScreen(),
            widget.Sep(),
            widget.GroupBox(
                active="fff0f0",
                inactive="808080",
                highlight_method="block",
                this_current_screen_border="c22b25",
                this_screen_border="619a75",
                other_current_screen_border="ba9998",
                other_screen_border="26914c",
                urgent_alert_method="block",
                urget_border="a528d2",
                disable_drag=True,
                use_mouse_wheel=False
            ),
            widget.Sep(),
            widget.Notify(
                foreground_low=colors["red"][1:],
                foreground_urgent=colors["red"][1:]
            ),
            widget.CurrentLayout(),
            widget.Spacer(),
            widget.Sep(),
            widget.Mpd(
                host="127.0.0.1",
                port=6600,
                reconnect=True,
                fmt_playing="%a [%A] %t [%v%%]",
            ),
            widget.Sep(),
            widget.HDDGraph(
                graph_color=colors["blue"],
                border_width=0,
                samples=10,
                frequency=5,
                type="box",
            ),
            widget.Wlan(
                interface="wlp3s0"),
            widget.MemoryGraph(
                graph_color=colors["green"],
                border_width=0,
                samples=10,
                frequency=2,
                type="box",
            ),
            widget.CPUGraph(
                graph_color=colors["red"],
                border_width=0,
                samples=10,
                frequency=2,
                type="box",
            ),
            widget.Battery(),
            widget.Sep(),
            widget.Systray(),
            widget.Sep(),
            widget.Clock(
                timezone="Europe/Berlin",
                format="%Y%m%d %a %H:%M:%S"
            ),
        ], 20
        ),
    ),
    Screen(
        top=bar.Bar([
            widget.CurrentScreen(),
            widget.Sep(),
            widget.GroupBox(
                active="fff0f0",
                inactive="808080",
                highlight_method="block",
                this_current_screen_border="c22b25",
                this_screen_border="619a75",
                other_current_screen_border="ba9998",
                other_screen_border="26914c",
                urgent_alert_method="block",
                urget_border="a528d2",
                disable_drag=True,
                use_mouse_wheel=False
            ),
            widget.Sep(),
            widget.CurrentLayout(),
            widget.Sep(),
            widget.Notify(
                foreground_low=colors["red"][1:],
                foreground_urgent=colors["red"][1:]
            ),
            widget.Spacer(),
            widget.Clock(
                timezone="Europe/Berlin",
                format="%Y%m%d %a %H:%M:%S"
            ),
        ], 20
        ),
    ),
]

# Drag floating layouts.
mouse = [
    Click([mod],
          "Button2",
          lazy.window.bring_to_front()
          ),
    Drag([mod],
         "Button1",
         lazy.window.set_position_floating(),
         start=lazy.window.get_position()
         ),
    Drag([mod],
         "Button3",
         lazy.window.set_size_floating(),
         start=lazy.window.get_size()
         )
]

floating_clients = [
    re.compile('^JACK'),
    re.compile('^Controls'),
    re.compile('^ssr-.*'),
    re.compile('^Help Browser'),
    re.compile('^Find externals'),
    re.compile('^Audio Settings'),
    re.compile('^MIDI Settings'),
    re.compile('^Find'),
    re.compile('^Pd search path'),
    re.compile('^Send a Pd message'),
    re.compile('^Instrument Tuner'),
]

dgroups_key_binder = None
dgroups_app_rules = []
follow_mouse_focus = True
bring_front_click = False
cursor_warp = False
floating_layout = layout.Floating()
auto_fullscreen = True
wmname = "LG3D"


def main(qtile):
    qtile.cmd_warning()


@hook.subscribe.screen_change
def restart_on_randr(qtile, ev):
    subprocess.run(['/usr/bin/killall', 'compton'])
    qtile.cmd_restart()


@hook.subscribe.client_new
def floating_dialogs(client):
    # wm_class = client.window.get_wm_class()
    # logger.setLevel(logging.INFO)
    # logger.info('New client window name: %s' % client.name)
    # logger.info('New client window class: %c' % wm_class)
    logger.setLevel(logging.WARNING)
    for client_regex in floating_clients:
        match = client_regex.match(client.name)
        if match:
            client.floating = True
    transient = client.window.get_wm_transient_for()
    if transient:
        client.floating = True


@hook.subscribe.startup
def autostart_background():
    subprocess.run(['/usr/bin/killall', 'compton'])
    subprocess.call(background)


@hook.subscribe.startup_once
def autostart_conky():
    subprocess.call(conky_network)
    subprocess.call(conky_general)


@hook.subscribe.startup_complete
def autostart_compton():
    subprocess.call(compton)
#    get_user_processes('compton')


# def get_user_processes(process_name):
#     for process in psutil.process_iter(attrs=['name', 'username']):
#         if process.info['username'] == getpass.getuser() and \
#                 process.info['name'] == process_name:
#             logger.setLevel(logging.INFO)
#             logger.info(process.pid)
#             logger.info(process.info['name'])
#             logger.setLevel(logging.WARNING)