# Copyright (c) 2010 Aldo Cortesi
# Copyright (c) 2010, 2014 dequis
# Copyright (c) 2012 Randall Ma
# Copyright (c) 2012-2014 Tycho Andersen
# Copyright (c) 2012 Craig Barnes
# Copyright (c) 2013 horsik
# Copyright (c) 2013 Tao Sauvage
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

import os
import subprocess
import psutil

import re

from typing import List  # noqa: F401

from libqtile import bar, hook, layout, qtile, widget
from libqtile.config import Click, Drag, DropDown, Group, Key, Match, ScratchPad, Screen
from libqtile.lazy import lazy

mod = "mod1"
if qtile.core.name == "x11":
    terminal = 'st'
    terminal_session = 'tabbed -c st -w'
    # terminal_session = 'st -e '
elif qtile.core.name == "wayland":
    terminal = 'alacritty'
    terminal_session = 'tabbed -c alacritty --embed'
    # terminal_session = 'alacritty -e'

computerrc = open('/home/zachir/.config/computerrc', 'r')
Lines = computerrc.readlines()
count = 0
for line in Lines:
    if ('inet' in Lines[count][:5]):
        break
    count += 1
inet = Lines[count][5:-1]

barcolor_cyan = "39c1ed"
barcolor_black = "000000"
barcolor_gray1 = "111111"
barcolor_gray2 = "222222"
barcolor_gray6 = "666666"
barcolor_gray8 = "888888"
barcolor_graya = "aaaaaa"
barcolor_white = "ffffff"
barcolor_red = "ff0000"
barcolor_magenta = "ff00ff"

def resize(qtile, direction):
    layout = qtile.current_layout
    child = layout.current
    parent = child.parent

    while parent:
        if child in parent.children:
            layout_all = False

            if (direction == "left" and parent.split_horizontal) or (
                direction == "up" and not parent.split_horizontal
            ):
                parent.split_ratio = max(5, parent.split_ratio - layout.grow_amount)
                layout_all = True
            elif (direction == "right" and parent.split_horizontal) or (
                direction == "down" and not parent.split_horizontal
            ):
                parent.split_ratio = min(95, parent.split_ratio + layout.grow_amount)
                layout_all = True

            if layout_all:
                layout.group.layout_all()
                break

        child = parent
        parent = child.parent

@lazy.function
def resize_left(qtile):
    resize(qtile, "left")

@lazy.function
def resize_right(qtile):
    resize(qtile, "right")

@lazy.function
def resize_up(qtile):
    resize(qtile, "up")

@lazy.function
def resize_down(qtile):
    resize(qtile, "down")

keys = [
    # Switch between windows
    Key([mod], "h", lazy.layout.left(), desc="Move focus down"),
    Key([mod], "l", lazy.layout.right(), desc="Move focus up"),
    Key([mod], "j", lazy.layout.down(), desc="Move focus down"),
    Key([mod], "k", lazy.layout.up(), desc="Move focus up"),
    Key([mod, "shift"], "space", lazy.layout.next(),
        desc="Move window focus to other window"),

    # swap columns
    Key([mod, "shift", "control"], "h", lazy.layout.swap_column_left()),
    Key([mod, "shift", "control"], "l", lazy.layout.swap_column_right()),

    # Move windows between left/right columns or move up/down in current stack.
    # Moving out of range in Columns layout will create new column.
    Key([mod, "shift"], "h", lazy.layout.shuffle_left(),
        desc="Move window to the left"),
    Key([mod, "shift"], "l", lazy.layout.shuffle_right(),
        desc="Move window to the right"),
    Key([mod, "shift"], "j", lazy.layout.shuffle_down(),
        desc="Move window down"),
    Key([mod, "shift"], "k", lazy.layout.shuffle_up(), desc="Move window up"),

    # Grow windows. If current window is on the edge of screen and direction
    # will be to screen edge - window would shrink.
    Key([mod, "control"], "h", lazy.layout.grow_left(),
        desc="Grow window to the left"),
    Key([mod, "control"], "l", lazy.layout.grow_right(),
        desc="Grow window to the right"),
    Key([mod, "control"], "j", lazy.layout.grow_down(),
        desc="Grow window down"),
    Key([mod, "control"], "k", lazy.layout.grow_up(), desc="Grow window up"),
    Key([mod], "n", lazy.layout.normalize(), desc="Reset all window sizes"),

    # Grow windows. If current window is on the edge of screen and direction
    # will be to screen edge - window would shrink.
    Key([mod, "mod4"], "h", resize_left,
        desc="Grow window to the left"),
    Key([mod, "mod4"], "l", resize_right,
        desc="Grow window to the right"),
    Key([mod, "mod4"], "j", resize_down,
        desc="Grow window down"),
    Key([mod, "mod4"], "k", resize_up, desc="Grow window up"),
    Key([mod], "n", lazy.layout.normalize(), desc="Reset all window sizes"),

    # Toggle between split and unsplit sides of stack.
    # Split = all windows displayed
    # Unsplit = 1 window displayed, like Max layout, but still with
    # multiple stack panes
    Key([mod, "shift"], "Return", lazy.layout.toggle_split(),
        desc="Toggle between split and unsplit sides of stack"),
    Key([mod], "Return", lazy.spawn(terminal), desc="Launch terminal"),
    Key([mod], "f", lazy.window.toggle_fullscreen(), desc="Toggle fullscreen"),
    Key([mod, "shift"], "n", lazy.spawn('Qminimize -u'), desc="Unminimize window"),
    Key([mod], "n", lazy.spawn('Qminimize -m'), desc="Minimize window"),
    Key([mod], "space", lazy.window.toggle_floating(),
            desc="Toggle floating"),

    # Toggle between different layouts as defined below
    Key([mod], "Tab", lazy.next_layout(), desc="Toggle between layouts"),
    Key([mod, "shift"], "Tab", lazy.prev_layout(), desc="Toggle between layouts"),
    Key([mod, "shift"], "q", lazy.window.kill(), desc="Kill focused window"),

    Key([mod, "shift"], "r", lazy.restart(), desc="Restart Qtile"),
    Key([mod, "shift"], "e", lazy.shutdown(), desc="Shutdown Qtile"),
    #Key([mod], "r", lazy.spawncmd(),
        #desc="Spawn a command using a prompt widget"),
]

groups = [Group(i) for i in "123456789"]

groups += [
        ScratchPad("scratchpad", [
        DropDown("htop", terminal + " htop",
            x=0.25, y=0.2, width=0.5, height=0.6,
            on_focus_lost_hide=True, warp_pointer=True),
        DropDown("term", terminal,
            x=0.25, y=0.2, width=0.5, height=0.6,
            on_focus_lost_hide=True, warp_pointer=True),
        DropDown("alsa", terminal + " pulsemixer",
            x=0.25, y=0.2, width=0.5, height=0.6,
            on_focus_lost_hide=True, warp_pointer=True),
        DropDown("blue", terminal + " bluetoothctl",
            x=0.25, y=0.2, width=0.5, height=0.6,
            on_focus_lost_hide=True, warp_pointer=True),
        DropDown("ncmp", terminal + " ncmpcpp",
            x=0.25, y=0.2, width=0.5, height=0.6,
            on_focus_lost_hide=True, warp_pointer=True),
        DropDown("mutt", terminal + " neomutt",
            x=0.25, y=0.2, width=0.5, height=0.6,
            on_focus_lost_hide=True, warp_pointer=True),
        DropDown("prof", terminal + " /usr/bin/profanity",
            x=0.25, y=0.2, width=0.5, height=0.6,
            on_focus_lost_hide=True, warp_pointer=True),
        DropDown("ircc", terminal + " /usr/bin/irssi",
            x=0.25, y=0.2, width=0.5, height=0.6,
            on_focus_lost_hide=True, warp_pointer=True),
        DropDown("todo", terminal + " /usr/bin/todo",
            x=0.25, y=0.2, width=0.5, height=0.6,
            on_focus_lost_hide=True, warp_pointer=True),
        DropDown("trem", terminal + " /usr/bin/tremc",
            x=0.25, y=0.2, width=0.5, height=0.6,
            on_focus_lost_hide=True, warp_pointer=True),
        ])
    ]

@hook.subscribe.startup
def autostart():
    home = os.path.expanduser('~/.config/autostart.sh')
    subprocess.call([home])

keys.extend([
    Key([mod, "control"], 'z', lazy.group['scratchpad'].dropdown_toggle('htop'),
        desc="Toggle htop scratchpad"),
    Key([mod, "control"], 'x', lazy.group['scratchpad'].dropdown_toggle('term'),
        desc="Toggle terminal scratchpad"),
    Key([mod, "control"], 'c', lazy.group['scratchpad'].dropdown_toggle('alsa'),
        desc="Toggle alsamixer scratchpad"),
    Key([mod, "control"], 'v', lazy.group['scratchpad'].dropdown_toggle('blue'),
        desc="Toggle alsamixer scratchpad"),
    Key([mod, "control"], 'b', lazy.group['scratchpad'].dropdown_toggle('ncmp'),
        desc="Toggle ncmpcpp scratchpad"),
    Key([mod, "control"], 'a', lazy.group['scratchpad'].dropdown_toggle('mutt'),
        desc="Toggle neomutt scratchpad"),
    Key([mod, "control"], 's', lazy.group['scratchpad'].dropdown_toggle('prof'),
        desc="Toggle profanity scratchpad"),
    Key([mod, "control"], 'd', lazy.group['scratchpad'].dropdown_toggle('ircc'),
        desc="Toggle irssi scratchpad"),
    Key([mod, "control"], 'f', lazy.group['scratchpad'].dropdown_toggle('todo'),
        desc="Toggle todo.txt scratchpad"),
    Key([mod, "control"], 'g', lazy.group['scratchpad'].dropdown_toggle('trem'),
        desc="Toggle tremc scratchpad"),
    ])

for i in "123456789":
    keys.extend([
        # mod1 + letter of group = switch to group
        Key([mod], i, lazy.group[i].toscreen(),
            desc="Switch to group {}".format(i)),

        # mod1 + shift + letter of group = switch to & move focused window to group
        Key([mod, "shift"], i, lazy.window.togroup(i, switch_group=False),
            desc="Switch to & move focused window to group {}".format(i)),
        # Or, use below if you prefer not to switch to that group.
        # # mod1 + shift + letter of group = move focused window to group
        # Key([mod, "shift"], i, lazy.window.togroup(i),
        #     desc="move focused window to group {}".format(i)),
    ])

layouts = [
    layout.Columns(
        border_focus=barcolor_gray8,
        border_focus_stack=barcolor_gray8,
        border_normal=barcolor_black,
        border_normal_stack=barcolor_black,
        insert_position=1,
        margin=5
    ),
    layout.Bsp(
        border_focus=barcolor_gray8,
        border_normal=barcolor_black,
        fair=False,
        margin=5
    ),
    # layout.Max(),
    # Try more layouts by unleashing below layouts.
    # layout.Stack(num_stacks=2),
    # layout.Matrix(),
    # layout.MonadTall(),
    # layout.MonadWide(),
    # layout.RatioTile(),
    # layout.Tile(),
    # layout.TreeTab(),
    # layout.VerticalTile(),
    # layout.Zoomy(),
]

widget_defaults = dict(
    font='mononoki Nerd Font Mono',
    fontsize=12,
    padding=3,
)
extension_defaults = widget_defaults.copy()

bar_array_1 = [
                widget.WindowName(
                    background=barcolor_cyan,
                    foreground=barcolor_black,
                    format='{state}{name}'
                ),
                widget.Chord(
                    chords_colors={
                        'launch': (barcolor_red, barcolor_white),
                    },
                    name_transform=lambda name: name.upper(),
                ),
                widget.TextBox("ZachIR", name="default",
                    background=barcolor_black,
                    foreground=barcolor_white
                ),
                widget.CPU(
                    background=barcolor_cyan,
                    foreground=barcolor_black,
                    format='CPU {load_percent}%',
                    update_interval=1.0
                ),
                widget.CPUGraph(
                    background=barcolor_cyan,
                    border_color=barcolor_black,
                    core='all',
                    fill_color=barcolor_graya,
                    graph_color=barcolor_white
                ),
                widget.Memory(
                    background=barcolor_black,
                    foreground=barcolor_white,
                    format='RAM {MemUsed: .0f}{mm}',
                    measure_mem='M',
                    measure_swap='M',
                    update_interval=1.0
                ),
                widget.MemoryGraph(
                    background=barcolor_black,
                    border_color=barcolor_cyan,
                    fill_color=barcolor_graya,
                    frequency=1,
                    graph_color=barcolor_white
                ),
                widget.Mpd2(
                    background=barcolor_cyan,
                    foreground=barcolor_black,
                    status_format='{play_status} {artist} - {title} \
[{repeat}{random}{single}{consume}{updating_db}]',
                    idle_format='{idle_message}',
                    idle_message='MPD',
                    host=os.path.expanduser('~/.config/mpd/socket'),
                    prepare_status={
                        'consume': 'c',
                        'random': 'z',
                        'repeat': 'r',
                        'single': 'y',
                        'updating_db': 'u' }
                ),
                widget.Net(
                    background=barcolor_black,
                    interface=inet
                )
            ]

bar_array_2 = [
                widget.Clock(
                    background=barcolor_black,
                    format='%Y-%m-%d %a %I:%M %p',
                    update_interval=1.0
                ),
                widget.QuickExit(
                    background=barcolor_cyan,
                    foreground=barcolor_black,
                    countdown_format='[ {}sec ]',
                    countdown_start=5,
                    default_text='[ exit ]',
                    timer_interval=1
                )
            ]

bar_systray = [ 
                widget.Systray(
                    background=barcolor_black
                )
            ]

bar_battery = [ 
                widget.Battery(
                    background=barcolor_cyan,
                    foreground=barcolor_black,
                    battery=0,
                    charge_char='+',
                    discharge_char='-',
                    empty_char='X',
                    format='{char}{percent:2.0%} {hour:d}:{min:02d}',
                    full_char='|',
                    low_foreground=barcolor_red,
                    low_percentage=0.15,
                    notify_below=0.15,
                    unknown_char='?',
                    update_interval=60
                )
            ]

bar_no_battery = [ 
                widget.TextBox("None", name="default",
                    background=barcolor_cyan,
                    foreground=barcolor_black
                )
            ]

bar_1 = bar_array_1
if (psutil.sensors_battery() != None):
    bar_1 = bar_1 + bar_battery
else:
    bar_1 = bar_1 + bar_no_battery
if qtile.core.name == "x11":
    bar_1 = bar_1 + bar_systray
bar_1 = bar_1 + bar_array_2

bar_2 = bar_array_1
if (psutil.sensors_battery() != None):
    bar_2 = bar_2 + bar_battery
else:
    bar_2 = bar_2 + bar_no_battery
bar_2 = bar_2 + bar_array_2

screens = [
    Screen(
        top=bar.Bar(
            [
                widget.CurrentLayoutIcon(
                    background=barcolor_cyan,
                    foreground=barcolor_black,
                    scale=0.8
                ),
                widget.GroupBox(
                    active=barcolor_white,
                    background=barcolor_black,
                    center_aligned=True,
                    highlight_color=barcolor_gray1,
                    highlight_method='line',
                    inactive=barcolor_gray6,
                    margin_x=2,
                    margin_y=5,
                    other_current_screen_border=barcolor_gray2,
                    other_screen_border=barcolor_gray2,
                    padding_y=5,
                    padding_x=3,
                    this_current_screen_border=barcolor_white,
                    this_screen_border=barcolor_white,
                    urgent_alert_method='block',
                    urgent_border=barcolor_magenta,
                    urgent_text=barcolor_magenta
                )
            ] + bar_1,
            24,
        ),
    ),
    Screen(
        top=bar.Bar(
            [
                widget.CurrentLayoutIcon(
                    background=barcolor_cyan,
                    foreground=barcolor_black,
                    scale=0.8
                ),
                widget.GroupBox(
                    active=barcolor_white,
                    background=barcolor_black,
                    center_aligned=True,
                    highlight_color=barcolor_gray1,
                    highlight_method='line',
                    inactive=barcolor_gray6,
                    margin_x=2,
                    margin_y=5,
                    other_current_screen_border=barcolor_gray2,
                    other_screen_border=barcolor_gray2,
                    padding_y=5,
                    padding_x=3,
                    this_current_screen_border=barcolor_white,
                    this_screen_border=barcolor_white,
                    urgent_alert_method='block',
                    urgent_border=barcolor_magenta,
                    urgent_text=barcolor_magenta
                )
            ] + bar_2,
            24,
        ),
    ),
]

# Drag floating layouts.
mouse = [
    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()),
    Click([mod], "Button2", lazy.window.bring_to_front())
]

dgroups_key_binder = None
dgroups_app_rules = []  # type: List
follow_mouse_focus = True
bring_front_click = False
cursor_warp = False
floating_layout = layout.Floating(float_rules=[
    # Run the utility of `xprop` to see the wm class and name of an X client.
    # *layout.Floating.default_float_rules,
    Match(title='FX: Track 1'), # REAPER
    Match(title='Torpedo Wall Of Sound (Two Notes Audio Engineering)'),
    Match(title='Add FX to: Track 1'), # REAPER
    Match(title='REAPER (loading)'), # REAPER
    Match(title='REAPER Query'), # REAPER
    Match(title='REAPER (initializing)'), # REAPER
    Match(title='Browse FX'), # REAPER
    Match(title='Ardour - Preferences'), # ardour
    Match(wm_instance_class='import'),  # ardour
    Match(wm_class=re.compile('ardour-6\.9\.0')),  # ardour
    Match(wm_class=re.compile("lin-vst-servertrack\.exe\.so")), #linvst
    Match(title='Edit Text on the Schematic:'), # LTspiceXVII
    Match(wm_class='confirmreset'),  # gitk
    Match(wm_class='makebranch'),  # gitk
    Match(wm_class='maketag'),  # gitk
    Match(title='branchdialog'),  # gitk
    Match(wm_class='ssh-askpass'),  # ssh-askpass
    Match(title=re.compile('Edit Guide.*')), # kdenlive
    Match(title=re.compile('Steam - News.*')), # SteamZZ
    Match(title='Create Snapshot'),  # timeshift-gtk
    Match(title='pinentry'),  # GPG key password entry
], border_focus=barcolor_gray8, border_normal=barcolor_black)
auto_fullscreen = False
focus_on_window_activation = "smart"
reconfigure_screens = True

# If things like steam games want to auto-minimize themselves when losing
# focus, should we respect this or not?
auto_minimize = False

# XXX: Gasp! We're lying here. In fact, nobody really uses or cares about this
# string besides java UI toolkits; you can see several discussions on the
# mailing lists, GitHub issues, and other WM documentation that suggest setting
# this string if your java app doesn't work correctly. We may as well just lie
# and say that we're a working one by default.
#
# We choose LG3D to ], border_focus='', border_normal=''aximize irony: it is a 3D non-reparenting WM written in
# java that happens to be on java's whitelist.
# wmname = "LG3D"