import logging
import mc.model
from PyQt5 import QtCore
from PyQt5 import QtWidgets
from PyQt5 import QtGui
import mc.gui.breathing_dlg
import mc.gui.breathing_notification
import mc.gui.rest_notification
import mc.gui.rest_dlg
from mc.gui.timing_settings_wt import TimingOverviewWt
from mc.model import SettingsM
import mc.mc_global

NEXT_STR = "Next >>"
PREV_STR = "<< Prev"
MARGIN_TOP_INT = 35
PARAGRAPH_SPACING_INT = 10


class IntroDlg(QtWidgets.QDialog):
    """
    The introduction wizard with examples of dialogs and functionality to adjust initial settings
    """
    close_signal = QtCore.pyqtSignal(bool)
    # -the boolean indicates whether or not we want the breathing dialog to open

    def __init__(self):
        super().__init__()

        self.wizard_qsw_w3 = QtWidgets.QStackedWidget()
        self.prev_qpb = QtWidgets.QPushButton(PREV_STR)
        self.next_qpb = QtWidgets.QPushButton(NEXT_STR)

        self.initial_setup = TimingInitSetupPage()
        self._init_ui()

    def _init_ui(self):
        welcome = WelcomePage()
        system_tray = SystemTrayPage()
        breathing_notification = BreathingNotificationPage()
        breathing_dialog = BreathingDialogPage()
        breathing_dialog_coming = BreathingDialogComing()

        self.wizard_qsw_w3.addWidget(welcome)
        self.wizard_qsw_w3.addWidget(system_tray)
        self.wizard_qsw_w3.addWidget(breathing_notification)
        self.wizard_qsw_w3.addWidget(breathing_dialog)
        self.wizard_qsw_w3.addWidget(self.initial_setup)
        self.wizard_qsw_w3.addWidget(breathing_dialog_coming)

        self.prev_qpb.clicked.connect(self.on_prev_clicked)
        self.next_qpb.clicked.connect(self.on_next_clicked)

        hbox_l3 = QtWidgets.QHBoxLayout()
        hbox_l3.addStretch(1)
        hbox_l3.addWidget(self.prev_qpb, stretch=1)
        hbox_l3.addWidget(self.next_qpb, stretch=1)
        hbox_l3.addStretch(1)

        vbox_l2 = QtWidgets.QVBoxLayout()
        vbox_l2.addWidget(self.wizard_qsw_w3)
        vbox_l2.addLayout(hbox_l3)

        self.setGeometry(300, 150, 650, 500)
        self.setLayout(vbox_l2)
        self.update_gui()
        self.show()

    def on_next_clicked(self):
        current_index_int = self.wizard_qsw_w3.currentIndex()
        if current_index_int >= self.wizard_qsw_w3.count() - 1:
            self.close_signal.emit(True)
            self.close()
        logging.debug("current_index_int = " + str(current_index_int))
        self.wizard_qsw_w3.setCurrentIndex(current_index_int + 1)
        self.update_gui()

    def on_prev_clicked(self):
        current_index_int = self.wizard_qsw_w3.currentIndex()
        if current_index_int <= 0:
            return
        logging.debug("current_index_int = " + str(current_index_int))
        self.wizard_qsw_w3.setCurrentIndex(current_index_int - 1)
        self.update_gui()

    def update_gui(self):
        current_index_int = self.wizard_qsw_w3.currentIndex()
        self.prev_qpb.setDisabled(current_index_int == 0)

        if current_index_int == self.wizard_qsw_w3.count() - 1:
            self.next_qpb.setText("Finish")  # "open breathing dialog"
        else:
            self.next_qpb.setText(NEXT_STR)


class WelcomePage(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        self._init_ui()

    def _init_ui(self):
        title_qll = QtWidgets.QLabel("Welcome")
        title_qll.setFont(mc.mc_global.get_font_xxlarge(i_bold=True))

        text_qll = QtWidgets.QLabel(
            "<p>Welcome to Mindfulness at the Computer!</p>"
            "<p>This application reminds you to stay aware of your breathing and to take breaks.</p>"
        )
        text_qll.setWordWrap(True)
        text_qll.setFont(mc.mc_global.get_font_xlarge())

        vbox_l2 = QtWidgets.QVBoxLayout()
        vbox_l2.addSpacing(MARGIN_TOP_INT)
        vbox_l2.addWidget(title_qll)
        vbox_l2.addStretch(1)
        vbox_l2.addWidget(text_qll)
        vbox_l2.addSpacing(PARAGRAPH_SPACING_INT)
        vbox_l2.addStretch(1)

        self.setLayout(vbox_l2)


class SystemTrayPage(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        self._init_ui()

    def _init_ui(self):
        title_qll = QtWidgets.QLabel("The system tray")
        title_qll.setFont(mc.mc_global.get_font_xxlarge(i_bold=True))
        title_qll.setAlignment(QtCore.Qt.AlignHCenter)

        description_qll = QtWidgets.QLabel(
            "When you run Mindfulness at the computer it is accessible via the system tray. "
            "From the menu that opens when clicking on this icon "
            "you can adjust settings or invoke a breathing or rest session"
        )
        description_qll.setWordWrap(True)
        description_qll.setFont(mc.mc_global.get_font_xlarge())

        system_tray_qll = QtWidgets.QLabel()
        system_tray_qll.setPixmap(QtGui.QPixmap(mc.mc_global.get_app_icon_path("icon-br.png")))
        system_tray_qll.setAlignment(QtCore.Qt.AlignHCenter)

        vbox_l3 = QtWidgets.QVBoxLayout()
        vbox_l3.addSpacing(MARGIN_TOP_INT)
        vbox_l3.addWidget(title_qll)
        vbox_l3.addStretch(1)
        vbox_l3.addWidget(description_qll)
        vbox_l3.addStretch(1)
        vbox_l3.addWidget(system_tray_qll)
        vbox_l3.addStretch(1)

        hbox_l2 = QtWidgets.QHBoxLayout()
        hbox_l2.addStretch(1)
        hbox_l2.addLayout(vbox_l3)
        hbox_l2.addStretch(1)

        self.setLayout(hbox_l2)


class BreathingNotificationPage(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        self._init_ui()

    def _init_ui(self):
        title_qll = QtWidgets.QLabel("The breathing notification")
        title_qll.setFont(mc.mc_global.get_font_xxlarge(i_bold=True))
        title_qll.setAlignment(QtCore.Qt.AlignHCenter)

        description_qll = QtWidgets.QLabel(
            "This notification pops up every once in a while. "
            "You can adjust how often you would like to get notified. "
            "If you like, you can start a breathing session from here"
        )
        description_qll.setWordWrap(True)
        description_qll.setFont(mc.mc_global.get_font_xlarge())

        breathing_notification = mc.gui.breathing_notification.BreathingNotification()
        breathing_notification.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
        breathing_notification.breathe_qpb.setDisabled(True)

        vbox_l3 = QtWidgets.QVBoxLayout()
        vbox_l3.addSpacing(MARGIN_TOP_INT)
        vbox_l3.addWidget(title_qll)
        vbox_l3.addStretch(1)
        vbox_l3.addWidget(description_qll)
        vbox_l3.addStretch(1)
        vbox_l3.addWidget(breathing_notification)
        vbox_l3.addStretch(1)

        hbox_l2 = QtWidgets.QHBoxLayout()
        hbox_l2.addStretch(1)
        hbox_l2.addLayout(vbox_l3)
        hbox_l2.addStretch(1)

        self.setLayout(hbox_l2)


class BreathingDialogPage(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        self._init_ui()

    def _init_ui(self):
        title_qll = QtWidgets.QLabel("The breathing dialog")
        title_qll.setFont(mc.mc_global.get_font_xxlarge(i_bold=True))
        title_qll.setAlignment(QtCore.Qt.AlignHCenter)

        description_qll = QtWidgets.QLabel(
            "This dialog helps you to relax and return to your breathing. "
            "Try it out, it is interactive!"
        )
        description_qll.setWordWrap(True)
        description_qll.setFont(mc.mc_global.get_font_xlarge())

        breathing_dlg = mc.gui.breathing_dlg.BreathingDlg()
        breathing_dlg.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
        breathing_dlg._close_qpb.setDisabled(True)

        vbox_l3 = QtWidgets.QVBoxLayout()
        vbox_l3.addSpacing(MARGIN_TOP_INT)
        vbox_l3.addWidget(title_qll)
        vbox_l3.addWidget(description_qll)
        vbox_l3.addStretch(1)
        vbox_l3.addWidget(breathing_dlg)
        vbox_l3.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)

        hbox_l2 = QtWidgets.QHBoxLayout()
        hbox_l2.addStretch(1)
        hbox_l2.addLayout(vbox_l3)
        hbox_l2.addStretch(1)

        self.setLayout(hbox_l2)


class TimingInitSetupPage(QtWidgets.QWidget):
    rest_settings_updated_from_intro_signal = QtCore.pyqtSignal(str)
    breathing_settings_updated_from_intro_signal = QtCore.pyqtSignal(str)

    def __init__(self):
        super().__init__()

        self.updating_gui_bool = False

        self.overview_qlw = TimingOverviewWt()
        self.grid = QtWidgets.QGridLayout()
        self.notification_interval_qsp = QtWidgets.QSpinBox()
        self.show_after_qsb = QtWidgets.QSpinBox()
        self.rest_interval_qsp = QtWidgets.QSpinBox()

        self._init_ui()
        self.update_gui()
        self._connect_slots_to_signals()

    def _init_ui(self):
        settings = mc.model.SettingsM.get()

        title_qll = QtWidgets.QLabel("Initial setup")
        title_qll.setFont(mc.mc_global.get_font_xxlarge(i_bold=True))

        intro_qll = QtWidgets.QLabel(
            "<p>Please select the initial setup parameters for the breathing dialog. "
            "It's possible to change the values later on using the settings window "
            '(available from the systray menu -> <strong>Open Settings</strong>).</p>'
        )
        intro_qll.setWordWrap(True)
        intro_qll.setFont(mc.mc_global.get_font_xlarge())

        header_qll = QtWidgets.QLabel("Time overview")
        header_qll.setFont(mc.mc_global.get_font_medium(i_bold=True))
        header_qll.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)

        notification_interval_qll = QtWidgets.QLabel("Time between breathing notifications")
        self.notification_interval_qsp.setValue(settings.breathing_reminder_interval_int)
        self.notification_interval_qsp.setMinimum(1)

        breathing_interval_qll = QtWidgets.QLabel("Breathing dialog after x nr of notifications")
        self.show_after_qsb.setValue(settings.breathing_reminder_nr_before_dialog_int)

        rest_interval_qll = QtWidgets.QLabel("Rest after minutes")
        self.rest_interval_qsp.setValue(settings.rest_reminder_interval)

        self.time_overview_vbox_l3 = QtWidgets.QVBoxLayout()
        self.time_overview_vbox_l3.setContentsMargins(12, 12, 12, 12)

        self.grid.setHorizontalSpacing(10)
        self.grid.setVerticalSpacing(20)
        self.grid.addWidget(title_qll, 1, 0, 1, 3)
        self.grid.addWidget(intro_qll, 2, 0, 1, 3)
        self.grid.addWidget(header_qll, 3, 2)

        self.grid.addWidget(notification_interval_qll, 5, 0)
        self.grid.addWidget(self.notification_interval_qsp, 5, 1)
        self.grid.addWidget(self.overview_qlw, 4, 2, 5, 1)
        self.grid.addWidget(breathing_interval_qll, 6, 0)
        self.grid.addWidget(self.show_after_qsb, 6, 1)
        self.grid.addWidget(rest_interval_qll, 7, 0)
        self.grid.addWidget(self.rest_interval_qsp, 7, 1)

        self.setLayout(self.grid)

        self.overview_qlw.update_gui_time_overview()

    def update_gui(self):
        self.updating_gui_bool = True

        settings = mc.model.SettingsM.get()
        self.notification_interval_qsp.setValue(settings.breathing_reminder_interval_int)
        self.show_after_qsb.setValue(settings.breathing_reminder_nr_before_dialog_int)
        self.rest_interval_qsp.setValue(settings.rest_reminder_interval_int)

        self.updating_gui_bool = False

    def _connect_slots_to_signals(self):
        self.notification_interval_qsp.valueChanged.connect(self.on_time_btw_notifications_value_changed)
        self.show_after_qsb.valueChanged.connect(self.on_dlg_after_nr_notifications_value_changed)
        self.rest_interval_qsp.valueChanged.connect(self.on_time_before_rest_value_changed)

    def on_time_btw_notifications_value_changed(self, i_new_value: int):
        logging.debug("on_time_btw_notifications_value_changed, i_new_value = " + str(i_new_value))
        SettingsM.update_breathing_reminder_interval(i_new_value)
        self.overview_qlw.update_gui_time_overview()
        self.breathing_settings_updated_from_intro_signal.emit('intro')

    def on_dlg_after_nr_notifications_value_changed(self, i_new_value: int):
        logging.debug("on_dlg_after_nr_notifications_value_changed, i_new_value = " + str(i_new_value))
        SettingsM.update_breathing_reminder_nr_per_dialog(i_new_value)
        self.overview_qlw.update_gui_time_overview()
        self.breathing_settings_updated_from_intro_signal.emit('intro')

    def on_time_before_rest_value_changed(self, i_new_value: int):
        logging.debug("on_time_before_rest_value_changed, i_new_value = " + str(i_new_value))
        SettingsM.update_rest_reminder_interval(i_new_value)
        self.overview_qlw.update_gui_time_overview()
        self.rest_settings_updated_from_intro_signal.emit('intro')


class BreathingDialogComing(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        self._init_ui()

    def _init_ui(self):
        title_qll = QtWidgets.QLabel("Finish")
        title_qll.setFont(mc.mc_global.get_font_xxlarge(i_bold=True))

        text_qll = QtWidgets.QLabel(
            "<p>When you click on finish and exit this wizard a breathing dialog will be shown. </p>"
            "<p><strong>Breathing in:</strong> Hover over the green box</p>"
            "<p><strong>Breathing out:</strong> Hover outside the green box</p>"
        )
        text_qll.setWordWrap(True)
        text_qll.setFont(mc.mc_global.get_font_xlarge())

        relaunch_wizard_qll = QtWidgets.QLabel(
            '<p>You can start this wizard again by choosing "Help" -> "Show intro wizard" in the settings '
            'window (available from the system tray icon menu)</p>'
        )
        relaunch_wizard_qll.setWordWrap(True)
        relaunch_wizard_qll.setFont(mc.mc_global.get_font_medium())
        relaunch_wizard_qll.setAlignment(QtCore.Qt.AlignCenter)

        vbox_l2 = QtWidgets.QVBoxLayout()
        vbox_l2.addSpacing(MARGIN_TOP_INT)
        vbox_l2.addWidget(title_qll)
        vbox_l2.addStretch(3)
        vbox_l2.addWidget(text_qll)
        vbox_l2.addStretch(3)
        vbox_l2.addWidget(relaunch_wizard_qll)
        vbox_l2.addStretch(1)

        self.setLayout(vbox_l2)