#!/usr/bin/env python3
import os
import subprocess
import time
import wprviews_tools as pv

"""
Budgie WindowPreviews
Author: Jacob Vlijm
Copyright=Copyright © 2017-2018 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/>.
"""

fpath = pv.previews


for f in os.listdir(fpath):
    try:
        os.remove(os.path.join(fpath, f))
    except FileNotFoundError:
        pass


# default resize is v_size, unless w exceeds threshold
max_w = 260
v_size = 160
# strings, to be used in the resize- commands
comm = str(max_w) + "x" + str(v_size)
# curr user
user = pv.user


def update_active(active, ws, id_list):
    # update currently active window
    hx_value = pv.get_hex(active)
    w_mention = hx_value + "." + ws
    if w_mention in id_list:
        # update window
        create_preview(w_mention)


def remove_preview(wid):
    file = os.path.join(fpath, wid + ".jpg")
    try:
        os.remove(file)
    except FileNotFoundError:
        pass


def create_preview(w_id):
    orig_id = w_id.split(".")[0]
    if pv.get_valid(orig_id):
        output_path = os.path.join(fpath, w_id + ".jpg")
        subprocess.Popen([
            "import", "-silent", "-window", orig_id, "-trim",
            "-resize", comm, output_path,
        ])


wins1 = []
wins2 = []
win_ids1 = []
queue = [[], [], [], [], []]
active1 = None
act_t = 1
idle = False
cycle = 1

r_timer = 0
r_index = 0

while True:

    time.sleep(cycle)

    # basic routine, create new ones, delete obsolete
    new_wins = []
    windata = pv.get(["wmctrl", "-lG"])
    curr_ws = pv.get_ws()
    if all([windata, not idle, curr_ws]):
        wins2 = [
            w.split() for w in windata.splitlines()
            if not any([name in w for name in [
                "w_moversplash", "PrVflash_prvwin"
            ]])
        ]
        for w in wins2:
            w[0] = ".".join([w[0], w[1]])
            del w[1:4]
        win_ids2 = [w[0] for w in wins2]
        new = [w for w in wins2 if w not in wins1]
        out = [w for w in wins1 if w not in wins2]

        for w in new:
            if w[0] in win_ids1:
                # doesn't need to be included in queue,
                # just create (overwrite) preview
                create_preview(w[0])
            else:
                # needs to be created *and* in queue
                new_wins.append(w[0])
                # create
                create_preview(w[0])

        for w in out:
            if not w[0] in win_ids2:
                # if windows are in win_ids2, they obviously still exist, but
                # are changed. No deletion needed, since they are overwritten
                remove_preview(w[0])

        """
        New windows will be placed in queue to refresh after 5 seconds of
        existence, to make sure not the "half loaded" image will remain.
        """

        for i in range(4):
            queue[i] = queue[i + 1]
        for item in queue[0]:
            # check existence / refresh
            if item in win_ids2:
                # create (overwrite)
                create_preview(item)

        queue[4] = new_wins

        """
        If windows are in front, refresh after every 9 seconds. Also refresh
        after focus change, *except* if we are dealing with a new window; then
        the window is recently created anyway, and updated after x seconds.
        Checking the window for existence in win_ids2 also has the advantage of
        checking by name. for excluded names, a preview will not be created.
        """

        curr_active = pv.get(["xdotool", "getactivewindow"])
        if curr_active:
            active2 = curr_active
            if active2 != active1:
                update_active(curr_active, curr_ws, win_ids1)
                act_t = 1
            else:
                act_t = act_t + 1
                if act_t % 9 == 0:
                    update_active(curr_active, curr_ws, win_ids1)
            active1 = active2

        """
        The windowlist, as reported in wmctrl -l, shows windows in
        chronlological order (newest at the bottom). below a section to renew
        the window images in rotation of that order, in a 15 sec routine, one
        per time (4 images updated per minute). Brand new images are excluded
        to prevent unnecessary fuel consumption.
        """

        if r_timer == 15:
            # once per 15 seconds, also check if user is still around
            if user not in subprocess.check_output("who").decode("utf-8"):
                break
            try:
                r_update = win_ids2[r_index]
                create_preview(r_update)
            except IndexError:
                r_index = 0
            else:
                if r_update not in new:
                    create_preview(r_update)
            r_index = r_index + 1
            r_timer = 0
        r_timer = r_timer + 1
        wins1 = wins2
        win_ids1 = win_ids2
    # If idle for more then 90 seconds ->
    # slow down checks, stop updating
    try:
        idle = int(pv.get("xprintidle")) / 1000 > 90
    except TypeError:
        pass
    else:
        cycle = 5 if idle else 1
