import wx

from clarabot_nano.control.account.change_password import ChangeAccountPasswordDialog
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 _2fa10PasswordChangeControlApplicationTester(ControlApplicationTester):
    """
    Test password change 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(8.0)
    def _phase_2(self, w: ControlWindow):
        """
        Check logged in and cancel setup wizard.
        """
        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

    @phase_timeout(5.0)
    def _phase_3(self, w: ControlWindow):
        """
        Wait until wizard is gone.
        """
        assert not self._get_modal_dialog(w, SimpleConfigurationWizard, require=False)
        return True

    def _phase_4(self, w: ControlWindow):
        """
        Start password edit.
        """
        w.AddPendingEvent(wx.CommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, w._change_password_item.GetId()))
        return True

    @phase_timeout(5.0)
    def _phase_5(self, w: ControlWindow):
        """
        Wait until dialog is shown.
        """
        self._get_modal_dialog(w, ChangeAccountPasswordDialog)
        return True

    def _phase_6(self, w: ControlWindow):
        """
        Start edit.
        NOTE: Changing to the same password is allowed because it cannot be checked? (salt->auth_key is different)
        """
        pwd_dialog = self._get_modal_dialog(w, ChangeAccountPasswordDialog)
        pwd_dialog._password_field.SetValue(self.password)
        pwd_dialog._password_field_2.SetValue(self.password)
        assert pwd_dialog._accept_button.IsEnabled()
        pwd_dialog.ProcessEvent(wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, pwd_dialog._accept_button.GetId()))
        return True

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

    def _phase_8(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_9(self, w: ControlWindow):
        """
        Wait until done.
        """
        pwd_dialog = self._get_modal_dialog(w, ChangeAccountPasswordDialog)
        message_dialog = self._get_modal_dialog(pwd_dialog, wx.GenericMessageDialog)
        assert message_dialog.GetMessage() == gettext("Successfully changed account password.")
        return True

    def _phase_10(self, w: ControlWindow):
        """
        Ack done.
        """
        pwd_dialog = self._get_modal_dialog(w, ChangeAccountPasswordDialog)
        message_dialog = self._get_modal_dialog(pwd_dialog, wx.GenericMessageDialog)
        message_dialog.EndModal(wx.ID_OK)
        return True

    @phase_timeout(5.0)
    def _phase_11(self, w: ControlWindow):
        """
        Wait until dialog is closed (by itself).
        """
        assert not self._get_modal_dialog(w, ChangeAccountPasswordDialog, require=False)
        return True
