#!/usr/bin/python3

import zmq
from argparse import ArgumentParser
from time import sleep
from threading import Thread
from ptcommon.logger import PTLogger
from ptcommon.ptdm_message import Message
from signal import signal
from signal import SIGINT
from signal import SIGTERM
from subprocess import Popen
from os import devnull
from os import environ

continue_listening = True

parser = ArgumentParser(description="pi-top desktop message service")
parser.add_argument("--no-journal", help="output to stdout not the journal", action="store_true")
parser.add_argument("--log-level", type=int, help="set the logging level from 10 (more verbose) to 50 (less verbose)", default=20)
args = parser.parse_args()

PTLogger.setup_logging("pt-desktop", args.log_level, args.no_journal is False)


def cleanup(signal, frame):
    global continue_listening

    PTLogger.debug("Closing sockets...")
    continue_listening = False
    poller.unregister(zmq_socket)


def _show_message(logger_text, message_text):
    PTLogger.info(logger_text)
    with open(devnull, 'w') as null:
        Popen(["/usr/bin/zenity", "--info", "--text", message_text], env=dict(environ, DISPLAY=":0.0", XAUTHORITY="/home/pi/.Xauthority"), stderr=null)


def display_critical_battery_warning_message():
    logger_text = "Displaying critical battery warning message"
    message_text = "Your pi-top's battery level is critically low. System will shut down shortly unless a charging cable is plugged in."
    _show_message(logger_text, message_text)


def display_low_battery_warning_message():
    logger_text = "Displaying low battery warning message"
    message_text = "Your pi-top's battery level is low. Please plug in a charging cable to prevent your system from shutting down."
    _show_message(logger_text, message_text)


def display_reboot_message():
    logger_text = "Displaying reboot message"
    message_text = "Recently detected hardware requires a system settings modification.\nPlease reboot to enable hardware support."
    _show_message(logger_text, message_text)


def display_unsupported_hardware_message():
    logger_text = "Displaying unsupported hardware message"
    message_text = "Recently detected hardware is not supported on your system."
    _show_message(logger_text, message_text)


def listen_thread():
    global poller
    global zmq_socket

    PTLogger.debug("Connecting to publish server...")
    zmq_context_listen = zmq.Context()
    zmq_socket = zmq_context_listen.socket(zmq.SUB)
    zmq_socket.setsockopt_string(zmq.SUBSCRIBE, "")
    zmq_socket.connect("tcp://127.0.0.1:3781")
    PTLogger.debug("Connected to publish server")

    sleep(0.5)

    while continue_listening:
        poller = zmq.Poller()
        poller.register(zmq_socket, zmq.POLLIN)
        events = poller.poll(500)

        for i in range(len(events)):
            message_string = zmq_socket.recv_string()
            message = Message.from_string(message_string)

            if (message.message_id() == Message.PUB_REBOOT_REQUIRED):
                display_reboot_message()
            elif (message.message_id() == Message.PUB_LOW_BATTERY_WARNING):
                display_low_battery_warning_message()
            elif (message.message_id() == Message.PUB_CRITICAL_BATTERY_WARNING):
                display_critical_battery_warning_message()
            elif (message.message_id() == Message.PUB_UNSUPPORTED_HARDWARE):
                display_unsupported_hardware_message()


# Capture and handle interrupts
signal(SIGINT, cleanup)
signal(SIGTERM, cleanup)

PTLogger.debug("Starting thread...")

thread = Thread(target=listen_thread)
thread.start()
thread.join()
zmq_socket.close()
