#!/usr/bin/env python3

"""
alarm_popup.py
"""

__author__ = ["Benjamin Mummery", "Tiago Sarmento"]
__credits__ = ["Benjamin Mummery", "Dónal Murray", "Tim Powell", "Tiago Sarmento"]
__license__ = "GPL"
__version__ = "0.0.1"
__maintainer__ = "Tiago Sarmento"
__email__ = "tiago.sarmento@stfc.ac.uk"
__status__ = "Prototype"

import os
from PySide2 import QtCore, QtGui, QtWidgets
from datetime import datetime


class AlarmWidget(QtWidgets.QWidget):
    def __init__(self, NativeUI, abstractAlarm, alarmCarrier, *args, **kwargs):
        super(AlarmWidget, self).__init__(*args, **kwargs)
        """Object containing information particular to one alarm.
        Created when alarm received from microcontroller, timeout after alarm signal stops.
        Is contained within alarmPopup"""
        popup_height = int(NativeUI.alarm_popup_width / 10.0)

        self.NativeUI = NativeUI
        self.alarmCarrier = alarmCarrier  # Needs to refer to its containing object

        self.layout = QtWidgets.QHBoxLayout()
        self.layout.setSpacing(0)
        self.layout.setMargin(0)
        self.alarmPayload = abstractAlarm.alarmPayload

        iconLabel = QtWidgets.QLabel()
        iconpath_check = os.path.join(
            self.NativeUI.iconpath, "exclamation-triangle-solid.png"
        )
        pixmap = QtGui.QPixmap(iconpath_check).scaledToHeight(popup_height)
        iconLabel.setPixmap(pixmap)
        self.layout.addWidget(iconLabel)

        self.textLabel = QtWidgets.QLabel()
        alarmLevel = self.alarmPayload["alarm_type"]
        self.textLabel.setText(
            self.alarmPayload["alarm_code"] + " - (" + alarmLevel + ")"
        )
        self.textLabel.setFixedWidth(NativeUI.alarm_popup_width)
        self.textLabel.setAlignment(QtCore.Qt.AlignCenter)
        self.textLabel.setFont(NativeUI.text_font)
        self.layout.addWidget(self.textLabel)

        self.setFixedHeight(popup_height)
        self.setLayout(self.layout)
        if self.alarmPayload["alarm_type"] == "PRIORITY_HIGH":
            self.setStyleSheet(
                "background-color:" + NativeUI.colors["red"].name() + ";"
            )
        elif self.alarmPayload["alarm_type"] == "PRIORITY_MEDIUM":
            self.setStyleSheet(
                "background-color" + NativeUI.colors["orange"].name() + ";"
            )
        self.setFixedSize(NativeUI.alarm_popup_width + popup_height, popup_height)

        self.installEventFilter(self)  # install response to press

    def eventFilter(self, source, event):
        """Repsond to button press by opening alarm page"""
        if event.type() == QtCore.QEvent.MouseButtonPress:
            self.NativeUI.widgets.page_buttons.alarms_button.click()
            self.NativeUI.widgets.alarms_page.setTab(
                self.NativeUI.widgets.alarms_page.button_list[0]
            )
        return False

    def get_priority(self):
        """Return alarm priority"""
        return self.alarmPayload["alarm_type"]

    def setFont(self, font) -> int:
        """
        Set the font for textLabel.
        """
        self.textLabel.setFont(font)
        return 0


class AlarmPopup(QtWidgets.QDialog):
    def __init__(self, NativeUI, *args, **kwargs):
        super(AlarmPopup, self).__init__(*args, **kwargs)
        """Container class for alarm widgets. Handles ordering and positioning of alarms.
        Ensures high priority alarms are listed above others. If 4 or more alarms are listed
        a 'X more alarms' is created and displayed to prevent the popup list getting too long.
        Needs to adjust its size whenever a widget is deleted. """
        self.setParent(NativeUI)  # ensures popup closes when main UI does
        self.alarmDict = {}
        self.NativeUI = NativeUI
        self.extraAlarms = AlarmExtrasWidget(NativeUI, self)

        self.layout = QtWidgets.QVBoxLayout()
        self.layout.setSpacing(0)
        self.layout.setMargin(0)
        self.setLayout(self.layout)

        self.location_on_window()
        self.setWindowFlags(
            QtCore.Qt.FramelessWindowHint
            | QtCore.Qt.Dialog
            | QtCore.Qt.WindowStaysOnTopHint
        )  # no window title

        self.shadow = QtWidgets.QGraphicsDropShadowEffect()
        self.shadow.setBlurRadius(20)
        self.shadow.setXOffset(10)
        self.shadow.setYOffset(10)

        self.timer = QtCore.QTimer()
        self.timer.setInterval(100)  # just faster than 60Hz
        self.timer.timeout.connect(self.adjustSize)
        self.timer.start()

        self.show()

    def clearAlarms(self):
        """Wipe all alarms out and clear dictionary"""
        for i in reversed(range(self.layout.count())):
            self.layout.itemAt(i).widget().setParent(None)
        self.adjustSize()
        self.setLayout(self.layout)
        self.alarmDict = {}
        return 0

    def addAlarm(self, abstractAlarm):
        """Creates a new alarmWidget and adds it to the container"""
        self.alarmDict[abstractAlarm.alarmPayload["alarm_code"]] = AlarmWidget(
            self.NativeUI, abstractAlarm, self
        )
        self.refresh_alarm_ordering()
        return 0

    def removeAlarm(self, abstractAlarm):
        """Creates a new alarmWidget and adds it to the container"""
        self.alarmDict[abstractAlarm.alarmPayload["alarm_code"]].setParent(None)
        self.alarmDict.pop(abstractAlarm.alarmPayload["alarm_code"])
        self.refresh_alarm_ordering()
        return 0

    def refresh_alarm_ordering(self):
        """Called whenever an alarm is created or destroyed, ensures the layout prioritises high alarms."""
        self.layout.removeWidget(self.extraAlarms)
        for key in self.alarmDict:
            self.layout.removeWidget(self.alarmDict[key])

        for key in self.alarmDict:
            if self.alarmDict[key].get_priority() == "PRIORITY_HIGH":
                if self.layout.count() == 4:
                    self.extraAlarms.update_text(
                        1 + len(self.alarmDict) - self.layout.count()
                    )
                    self.layout.addWidget(self.extraAlarms)
                    break
                self.layout.addWidget(self.alarmDict[key])

        if self.layout.count() < 5:
            for key in self.alarmDict:
                if self.layout.count() == 3:
                    self.extraAlarms.update_text(
                        len(self.alarmDict) - self.layout.count()
                    )
                    self.layout.addWidget(self.extraAlarms)
                    break
                if self.alarmDict[key].get_priority() == "PRIORITY_LOW":
                    self.layout.addWidget(self.alarmDict[key])

    def location_on_window(self):
        """Position the popup as defined here"""
        screen = QtWidgets.QDesktopWidget().screenGeometry()
        x = screen.width() - screen.width() / 2
        y = 0  # screen.height() - widget.height()
        self.move(x, y)
        return 0

    def localise_text(self, text: dict) -> int:
        """
        Change the language of text elements.
        """
        pass


class AlarmExtrasWidget(QtWidgets.QWidget):
    """Widget created to indicate there are many alarms not listed."""

    def __init__(self, NativeUI, alarmCarrier, *args, **kwargs):
        super(AlarmExtrasWidget, self).__init__(*args, **kwargs)

        popup_height = int(NativeUI.alarm_popup_width / 10.0)

        self.NativeUI = NativeUI
        self.alarmCarrier = alarmCarrier  # Needs to refer to its containing object

        self.layout = QtWidgets.QHBoxLayout()
        self.layout.setSpacing(0)
        self.layout.setMargin(0)

        iconLabel = QtWidgets.QLabel()
        iconpath_check = os.path.join(
            self.NativeUI.iconpath, "exclamation-triangle-solid.png"
        )
        pixmap = QtGui.QPixmap(iconpath_check).scaledToHeight(popup_height)
        iconLabel.setPixmap(pixmap)
        self.layout.addWidget(iconLabel)

        self.textLabel = QtWidgets.QLabel()
        self.textLabel.setText("1 More Alarms")
        self.textLabel.setFixedWidth(NativeUI.alarm_popup_width)
        self.textLabel.setAlignment(QtCore.Qt.AlignCenter)
        self.textLabel.setFont(NativeUI.text_font)
        self.layout.addWidget(self.textLabel)

        self.setFixedHeight(popup_height)
        self.setLayout(self.layout)
        self.setStyleSheet("background-color: " + NativeUI.colors["red"].name() + ";")
        self.installEventFilter(self)
        self.setFixedSize(NativeUI.alarm_popup_width + popup_height, popup_height)

    def update_text(self, num):
        self.textLabel.setText(str(num) + " More Alarms")

    def eventFilter(self, source, event):
        if event.type() == QtCore.QEvent.MouseButtonPress:
            self.NativeUI.widgets.page_buttons.alarms_button.click()
        return False

    def get_priority(self):
        return self.alarmPayload["alarm_type"]
