import os
import sys

import wx

from clarabot_nano.common.core.message import MSG_TYPE_GATEWAY_LOGIN
from clarabot_nano.control.client import WxCoreInterface
from clarabot_nano.control.two_factor import TwoFactorGatewayRequestMixin
from clarabot_nano.control.utility import Slots, change_font_to_bold, change_foreground_color_to_dimmed


class ControlLogin(wx.Panel, Slots, TwoFactorGatewayRequestMixin):
    """
    gateway not logged in -> login page
    after login start wizard for initial setup
    """

    def __init__(self, core_interface: WxCoreInterface, parent):
        wx.Panel.__init__(self, parent)
        Slots.__init__(self)
        TwoFactorGatewayRequestMixin.__init__(self, core_interface)

        layout = wx.BoxSizer(wx.VERTICAL)
        if sys.platform.startswith("darwin"):
            layout.AddSpacer(18)  # Compensate for missing menubar on the window.
        layout.AddStretchSpacer(2)

        self._title_label = wx.StaticText(
            self, wx.ID_ANY, gettext("Log in to Clarabot"), style=wx.ALIGN_CENTRE_HORIZONTAL
        )
        change_foreground_color_to_dimmed(self._title_label)
        change_font_to_bold(self._title_label)
        layout.Add(self._title_label, 3, wx.ALL | wx.EXPAND)

        h_margin_layout = wx.BoxSizer(wx.HORIZONTAL)
        layout.Add(h_margin_layout, 0, wx.ALL | wx.EXPAND)
        h_margin_layout.AddStretchSpacer(1)
        form_layout = wx.BoxSizer(wx.VERTICAL)
        h_margin_layout.Add(form_layout, 6, wx.ALL | wx.ALIGN_CENTER)
        h_margin_layout.AddStretchSpacer(1)

        self._email_field = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER)
        self._email_field.SetHint(gettext("Email address"))
        self.Bind(wx.EVT_TEXT, self._on_text_changed, self._email_field)
        self.Bind(wx.EVT_TEXT_ENTER, self._on_email_return, self._email_field)
        form_layout.Add(self._email_field, 0, wx.ALL | wx.EXPAND, 4)
        self._password_field = wx.TextCtrl(self, style=wx.TE_PASSWORD | wx.TE_PROCESS_ENTER)
        self._password_field.SetHint(gettext("Password"))
        self.Bind(wx.EVT_TEXT, self._on_text_changed, self._password_field)
        self.Bind(wx.EVT_TEXT_ENTER, self._on_password_return, self._password_field)
        form_layout.Add(self._password_field, 0, wx.ALL | wx.EXPAND, 4)

        self._login_btn = wx.Button(self, wx.ID_ANY, gettext("Log in"))
        self.Bind(wx.EVT_BUTTON, self._on_login_clicked, self._login_btn)
        form_layout.Add(self._login_btn, 0, wx.ALL | wx.EXPAND, 4)

        self._command_result_label = wx.StaticText(
            self, wx.ID_ANY, "", style=wx.ST_NO_AUTORESIZE | wx.ALIGN_CENTRE_HORIZONTAL
        )
        self._command_result_label.Wrap(300)  # 2FA results may be long
        layout.Add(self._command_result_label, 1, wx.ALL | wx.EXPAND, 4)
        layout.AddStretchSpacer(4)

        self.SetSizer(layout)

        self.bind_signal(core_interface.gateway_command_result, self._on_gateway_command_result)

        # init ui
        self._on_text_changed()

    def is_email_valid_for_submission(self):
        return self._email_field.GetLineLength(0) > 0

    def is_password_valid_for_submission(self):
        return self._password_field.GetLineLength(0) > 0

    def _on_text_changed(self, *args):
        self._login_btn.Enable(self.is_email_valid_for_submission() and self.is_password_valid_for_submission())

    def _on_email_return(self, event):
        if self.is_email_valid_for_submission():
            if self.is_password_valid_for_submission():
                self.ProcessEvent(wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self._login_btn.GetId()))
            else:
                self._password_field.SetFocus()

    def _on_password_return(self, event):
        if self.is_password_valid_for_submission():
            if self.is_email_valid_for_submission():
                self.ProcessEvent(wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self._login_btn.GetId()))
            else:
                self._email_field.SetFocus()

    def _on_login_clicked(self, event):
        self._start_gateway_request(
            MSG_TYPE_GATEWAY_LOGIN,
            {
                "email": self._email_field.GetLineText(0),
                "password": self._password_field.GetLineText(0),
                "server_session_key": os.urandom(16),  # session encryption secret part stored by the server
            },
            gettext("Requesting log in..."),
        )
        self._command_result_label.SetLabelText(gettext("Requesting log in..."))

    def _set_feedback_text(self, text: str):
        self._command_result_label.SetLabelText(text)

    def _enable_ui(self, b: bool):
        self._email_field.Enable(b)
        self._password_field.Enable(b)
        self._login_btn.Enable(b)

    def _gateway_request_ended(self, response_received, result):
        self._password_field.Clear()
        if self._email_field.GetLineLength(0):
            self._password_field.SetFocus()
        else:
            self._email_field.SetFocus()
