import wx

from clarabot_nano.control.configure.basic.wizard import SimpleConfigurationWizard
from clarabot_nano.control.page.status import ControlStatus
from clarabot_nano.control.window import ControlWindow
from clarabot_nano.development.spawn.control.tester import ControlApplicationTester, phase_timeout


class _2fa10LoginControlApplicationTester(ControlApplicationTester):
    """
    Test initial logging in with Nano while 2FA mode 10 is required.
    """

    def __init__(self, *args, email=None, password=None, **kwargs):
        ControlApplicationTester.__init__(self, *args, **kwargs)
        self.email = email
        self.password = password

    @phase_timeout(5.0)
    def _phase_0(self, w: ControlWindow):
        """
        Wait until login is shown.
        """
        self._check_waiting_login_get_central_widget(w)
        return True

    def _phase_1(self, w: ControlWindow):
        """
        Start login.
        """
        login_widget = self._check_waiting_login_get_central_widget(w)

        login_widget._email_field.SetValue(self.email)
        login_widget._password_field.SetValue(self.password)
        login_widget.ProcessEvent(wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, login_widget._login_btn.GetId()))

        return True

    @phase_timeout(15.0)
    def _phase_2(self, w: ControlWindow):
        """
        Wait until 2FA code entry is shown.
        """
        code_entry = self._get_text_entry_dialog(w)
        assert code_entry.GetTitle() == gettext("Enter 2FA code")
        return True

    def _phase_3(self, w: ControlWindow):
        """
        Submit bad code.
        """
        code_entry = self._get_text_entry_dialog(w)
        code_entry.SetValue("01010")  # constant "incorrect"
        code_entry.EndModal(wx.ID_OK)
        return True

    @phase_timeout(5.0)
    def _phase_4(self, w: ControlWindow):
        """
        Wait until login is shown with error.
        """
        assert not self._get_text_entry_dialog(w, require=False)
        login_widget = self._check_waiting_login_get_central_widget(w)
        assert login_widget._command_result_label.GetLabelText() == gettext("Two-factor authentication is denied or invalid.")
        return True

    def _phase_5(self, w: ControlWindow):
        """
        Start login again.
        """
        login_widget = self._check_waiting_login_get_central_widget(w)
        login_widget._password_field.SetValue(self.password)
        login_widget.ProcessEvent(wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, login_widget._login_btn.GetId()))
        return True

    @phase_timeout(8.0)
    def _phase_6(self, w: ControlWindow):
        """
        Wait until 2FA code entry is shown.
        """
        code_entry = self._get_text_entry_dialog(w)
        assert code_entry.GetTitle() == gettext("Enter 2FA code")
        return True

    def _phase_7(self, w: ControlWindow):
        """
        Submit good code.
        """
        code_entry = self._get_text_entry_dialog(w)
        code_entry.SetValue("10101")  # constant "correct"
        code_entry.EndModal(wx.ID_OK)
        return True

    @phase_timeout(5.0)
    def _phase_8(self, w: ControlWindow):
        """
        Check logged in.
        """
        central_widget = w.central_widget()
        assert isinstance(central_widget, ControlStatus)
        d = self._get_modal_dialog(w, SimpleConfigurationWizard)
        self._find_send_command_event(d, wx.ID_CANCEL, wx.wxEVT_COMMAND_BUTTON_CLICKED)
        return True
