#!/usr/bin/env python3
import gi.repository
gi.require_version("Gdk", "3.0")
from gi.repository import Gio, Gdk
import subprocess
import time
import os
import psutil


"""
Budgie TakeaBreak
Author: Jacob Vlijm
Copyright © 2017-2022 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/>.
"""


dcpath = "/com/solus-project/budgie-panel/applets/"
tab_key = "org.ubuntubudgie.plugins.takeabreak"
user = os.environ["USER"]
tab_settings = Gio.Settings.new(tab_key)
# get current settings
auto_unlock = tab_settings.get_boolean("unlockafterbreak")
awaketime = tab_settings.get_int("awaketime") * 60
sleeptime = tab_settings.get_int("sleeptime") * 60
mode = tab_settings.get_string("mode")
notify_msg = tab_settings.get_boolean("showmessage")
notify_time = 15
from_unidle = tab_settings.get_boolean("smartresume")
message = "Break in " + str(notify_time) + " seconds"
tabcountdown_path = os.path.dirname(os.path.abspath(__file__))


def get_idle():
    return int(subprocess_tasks("getval", ["xprintidle"], 0))


def idle_sleep():
    curr_idle1 = get_idle()
    while True:
        time.sleep(3)
        curr_idle2 = get_idle()
        if curr_idle2 <= curr_idle1:
            break
        else:
            curr_idle1 = curr_idle2


def subprocess_tasks(task, command_list, fallbackval=None):
    if task == "getval":
        try:
            return subprocess.check_output(command_list).decode("utf-8")
        except Exception:
            print("unable to get result from" + str(command_list))
            return fallbackval
    elif task == "run_sync":
        try:
            subprocess.call(command_list)
        except Exception:
            pass
    elif task == "run_async":
        try:
            subprocess.Popen(command_list)
        except Exception:
            pass


def write_nextbreak():
    next_break = time.time() + awaketime
    open("/tmp/nextbreak_" + user, "wt").write(str(next_break))


def sendmessage(title, message, icon=""):
    subprocess.Popen(["notify-send", "-i", icon, title, message])


def take_a_break():
    gdkdisplay = Gdk.Display.get_default()
    screens = [
        gdkdisplay.get_monitor(n).get_model() for n in range(
            gdkdisplay.get_n_monitors()
        )]
    if mode == "message":
        command = tabcountdown_path + "/message_window"
        subprocess_tasks("run_async", [command, str(sleeptime)])
    else:
        for scr in screens:
            if mode == "rotate":
                subprocess_tasks(
                    "run_sync",
                    ["xrandr", "--output", scr, "--rotate", "inverted"]
                )
            elif mode == "dim":
                subprocess_tasks(
                    "run_sync",
                    ["xrandr", "--output", scr, "--brightness", "0.1"]
                )
            elif mode == "lock":
                subprocess_tasks(
                    "run_async",
                    ["gnome-screensaver-command", "-l"]
                )
    time.sleep(sleeptime)
    for scr in screens:
        if auto_unlock:
            subprocess_tasks(
                "run_async",
                ["gnome-screensaver-command", "-d"]
            )
        time.sleep(2)
        if mode == "rotate":
            subprocess_tasks(
                "run_sync",
                ["xrandr", "--output", scr, "--rotate", "normal"]
            )
            time.sleep(0.2)
        elif mode == "dim":
            subprocess_tasks(
                "run_sync",
                ["xrandr", "--output", scr, "--brightness", "1"]
            )
            time.sleep(0.2)
    if from_unidle:
        idle_sleep()


if from_unidle:
    idle_sleep()


def lockscreen_check():
    lockproc = "gnome-screensaver-dialog"
    try:
        return lockproc in (p.name() for p in psutil.process_iter())
    except psutil.NoSuchProcess:
        return False


while True:
    write_nextbreak()
    time.sleep(awaketime - notify_time)
    if notify_msg:
        sendmessage("Take a break", message, "takeabreak-symbolic")
    time.sleep(notify_time)
    take_a_break()
