#!/usr/bin/env python3
import subprocess
import os
import ast
import time

"""
Hot Corners
Author: Jacob Vlijm
Copyright © 2017-2020 Ubuntu Budgie Developers
Website=https://ubuntubudgie.org
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or any later version. This
program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details. You
should have received a copy of the GNU General Public License along with this
program.  If not, see <http://www.gnu.org/licenses/>.
"""

user = os.environ["USER"]
orig_minimized = "/tmp/" + user + "sd_orig_minimized"
active_minimized = "/tmp/" + user + "sd_active_minimized"
front = "/tmp/" + user + "_sd_front"


ignore = [
    "= _NET_WM_WINDOW_TYPE_DOCK",
    "= _NET_WM_WINDOW_TYPE_DESKTOP",
]


def get(cmd):
    try:
        output = subprocess.check_output(cmd)

        if output:
            output = output.decode("utf-8").strip()
    except subprocess.CalledProcessError:
        output = None

    return output

def get_currws():
    return [l.split()[0] for l in get(
        ["wmctrl", "-d"]).splitlines() if "*" in l][0]


def get_valid(w_id):
    # see if the window is a valid one (type)
    w_data = get(["xprop", "-id", w_id])
    if w_data:
        return True if not any([t in w_data for t in ignore]) else False
    else:
        return False


def get_state(w_id):
    return "window state: Iconic" in get(["xprop", "-id", w_id, "WM_STATE"])

tominimize = False
try:
    currws = get_currws()
    allwinsdata = [w.split() for w in get(["wmctrl", "-l"]).splitlines()]
    winsoncurr = [w[0] for w in allwinsdata if w[1] == currws]
    relevant = [w for w in winsoncurr if get_valid(w)]
    # windows on current workspace, normal state
    tominimize = [w for w in relevant if not get_state(w)]
except:
    exit()

if tominimize:
    # get currently active window
    try:
        active_w = get(["xdotool", "getactivewindow"])
    except subprocess.CalledProcessError:
        active_w = None
    # remove possible previous window data
    for f in [orig_minimized, active_minimized, front]:
        try:
            os.remove(f)
        except FileNotFoundError:
            pass
    # minimize normal-state windows
    for w in tominimize:
        try:
            subprocess.Popen(["xdotool", "windowminimize", w])
        except subprocess.CalledProcessError:
            pass
    # remember already minimized windows
    minimized = [w for w in relevant if w not in tominimize]
    open(orig_minimized, "wt").write(str(minimized))
    # remember actively minimized
    open(active_minimized, "wt").write(str(tominimize))
    # remember active window
    if active_w:
        open(front, "wt").write(str(active_w))

else:
    try:
        toshow = ast.literal_eval(open(active_minimized).read())
        ignored = ast.literal_eval(open(orig_minimized).read())
        active_w = open(front).read()
    except FileNotFoundError:
        pass
    else:
        allwins = sorted(toshow + ignored)
        compare = sorted(relevant)
        if allwins == compare:
            # toshow.append(active_w)
            for w in toshow:
                try:
                    subprocess.Popen(["wmctrl", "-ia", w])
                except subprocess.CalledProcessError:
                    pass

            time.sleep(0.05)
            try:
                subprocess.Popen(["wmctrl", "-ia", active_w])
            except subprocess.CalledProcessError:
                pass
            # remove possible previous window data
            for f in [orig_minimized, active_minimized]:
                try:
                    os.remove(f)
                except FileNotFoundError:
                    pass
