from logging import getLogger

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QLayout, QMessageBox, QFrame
from legendary.core import LegendaryCore

from rare.shared import ArgumentsSingleton
from rare.ui.components.dialogs.login.landing_page import Ui_LandingPage
from rare.ui.components.dialogs.login.login_dialog import Ui_LoginDialog
from rare.utils.misc import icon
from rare.widgets.dialogs import BaseDialog
from rare.widgets.sliding_stack import SlidingStackedWidget
from .browser_login import BrowserLogin
from .import_login import ImportLogin

logger = getLogger("LoginDialog")


class LandingPage(QFrame):
    def __init__(self, parent=None):
        super(LandingPage, self).__init__(parent=parent)
        self.setFrameStyle(self.StyledPanel)
        self.ui = Ui_LandingPage()
        self.ui.setupUi(self)


class LoginDialog(BaseDialog):

    def __init__(self, core: LegendaryCore, parent=None):
        super(LoginDialog, self).__init__(parent=parent)
        self.setWindowFlags(
            Qt.Window
            | Qt.Dialog
            | Qt.CustomizeWindowHint
            | Qt.WindowSystemMenuHint
            | Qt.WindowTitleHint
            | Qt.WindowMinimizeButtonHint
            | Qt.WindowCloseButtonHint
            | Qt.MSWindowsFixedSizeDialogHint
        )

        self.ui = Ui_LoginDialog()
        self.ui.setupUi(self)

        self.logged_in: bool = False

        self.core = core
        self.args = ArgumentsSingleton()

        self.login_stack = SlidingStackedWidget(parent=self)
        self.login_stack.setMinimumWidth(480)
        self.ui.login_stack_layout.addWidget(self.login_stack)

        self.landing_page = LandingPage(self.login_stack)
        self.login_stack.insertWidget(0, self.landing_page)

        self.browser_page = BrowserLogin(self.core, self.login_stack)
        self.login_stack.insertWidget(1, self.browser_page)
        self.browser_page.success.connect(self.login_successful)
        self.browser_page.changed.connect(
            lambda: self.ui.next_button.setEnabled(self.browser_page.is_valid())
        )
        self.import_page = ImportLogin(self.core, self.login_stack)
        self.login_stack.insertWidget(2, self.import_page)
        self.import_page.success.connect(self.login_successful)
        self.import_page.changed.connect(lambda: self.ui.next_button.setEnabled(self.import_page.is_valid()))

        # # NOTE: The real problem is that the BrowserLogin page has a huge QLabel with word-wrapping enabled.
        # # That forces the whole form to vertically expand instead of horizontally. Since the form is not shown
        # # on the first page, the internal Qt calculation for the size of that form calculates it by expanding it
        # # vertically. Once the form becomes visible, the correct calculation takes place and that is why the
        # # dialog reduces in height. To avoid that, calculate the bounding size of all forms and set it as the
        # # minumum size
        # self.login_stack.setMinimumSize(
        #     self.landing_page.sizeHint().expandedTo(
        #         self.browser_page.sizeHint().expandedTo(self.import_page.sizeHint())
        #     )
        # )

        self.login_stack.setFixedHeight(
            max(
                self.landing_page.heightForWidth(self.login_stack.minimumWidth()),
                self.browser_page.heightForWidth(self.login_stack.minimumWidth()),
                self.import_page.heightForWidth(self.login_stack.minimumWidth()),
            )
        )

        self.ui.next_button.setEnabled(False)
        self.ui.back_button.setEnabled(False)

        self.landing_page.ui.login_browser_radio.clicked.connect(lambda: self.ui.next_button.setEnabled(True))
        self.landing_page.ui.login_browser_radio.clicked.connect(self.browser_radio_clicked)
        self.landing_page.ui.login_import_radio.clicked.connect(lambda: self.ui.next_button.setEnabled(True))
        self.landing_page.ui.login_import_radio.clicked.connect(self.import_radio_clicked)

        self.ui.exit_button.clicked.connect(self.reject)
        self.ui.back_button.clicked.connect(self.back_clicked)
        self.ui.next_button.clicked.connect(self.next_clicked)

        self.login_stack.setCurrentWidget(self.landing_page)

        self.ui.exit_button.setIcon(icon("fa.remove"))
        self.ui.back_button.setIcon(icon("fa.chevron-left"))
        self.ui.next_button.setIcon(icon("fa.chevron-right"))

        # lk: Set next as the default button only to stop closing the dialog when pressing enter
        self.ui.exit_button.setAutoDefault(False)
        self.ui.back_button.setAutoDefault(False)
        self.ui.next_button.setAutoDefault(True)

        self.ui.main_layout.setSizeConstraint(QLayout.SetFixedSize)

    def back_clicked(self):
        self.ui.back_button.setEnabled(False)
        self.ui.next_button.setEnabled(True)
        self.login_stack.slideInWidget(self.landing_page)

    def browser_radio_clicked(self):
        self.login_stack.slideInWidget(self.browser_page)
        self.ui.back_button.setEnabled(True)
        self.ui.next_button.setEnabled(False)

    def import_radio_clicked(self):
        self.login_stack.slideInWidget(self.import_page)
        self.ui.back_button.setEnabled(True)
        self.ui.next_button.setEnabled(self.import_page.is_valid())

    def next_clicked(self):
        if self.login_stack.currentWidget() is self.landing_page:
            if self.landing_page.ui.login_browser_radio.isChecked():
                self.browser_radio_clicked()
            if self.landing_page.ui.login_import_radio.isChecked():
                self.import_radio_clicked()
        elif self.login_stack.currentWidget() is self.browser_page:
            self.browser_page.do_login()
        elif self.login_stack.currentWidget() is self.import_page:
            self.import_page.do_login()

    def login(self):
        if self.args.test_start:
            self.reject()
        self.open()

    def login_successful(self):
        try:
            if not self.core.login():
                raise ValueError("Login failed.")
            self.logged_in = True
            self.accept()
        except Exception as e:
            logger.error(str(e))
            self.core.lgd.invalidate_userdata()
            self.ui.next_button.setEnabled(False)
            self.logged_in = False
            QMessageBox.warning(None, self.tr("Login error"), str(e))

