import base64
from typing import Optional, Tuple, List

import wx

from clarabot_nano.control.icon import get_wx_nano_icon
from clarabot_nano.control.label import AutoHeightWrappedStaticText
from clarabot_nano.utility.serialize import msgpack_loads


class DriveAttachDialog(wx.Dialog):
    def __init__(self, parent):
        wx.Dialog.__init__(
            self,
            parent,
            wx.ID_ANY,
            gettext("Attach a room to the drive"),
            style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
        )
        self.SetSizeHints(450, 400)
        self.SetIcon(get_wx_nano_icon())

        layout = wx.BoxSizer(wx.VERTICAL)

        self._top_label = AutoHeightWrappedStaticText(
            self,
            wx.ID_ANY,
            gettext(
                "To attach a room to the drive securely, the room's current configuration must be manually "
                "entered after verification.\n Go to the room's permission settings in the web application. "
                "After checking it, copy the state data here from the advanced menu."
            ),
        )
        layout.Add(self._top_label, 0, wx.ALL | wx.EXPAND, 8)

        self._data = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_RICH | wx.TE_MULTILINE | wx.TE_BESTWRAP)
        layout.Add(self._data, 1, wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, 8)

        buttons = self.CreateButtonSizer(wx.OK | wx.CANCEL)
        if buttons:
            layout.Add(buttons, 0, wx.ALL | wx.EXPAND, 8)
        self._accept_button = self.FindWindow(self.GetAffirmativeId())

        self.SetSizer(layout)

        self.Bind(wx.EVT_TEXT, self._on_data, self._data)
        # self.Bind(wx.EVT_BUTTON, self._on_accept, self._accept_button)

        self._on_data()

    def _on_data(self, *args):
        self._accept_button.Enable(bool(self.get_data()))

    def get_data(self) -> Optional[Tuple[str, List[str]]]:
        v = self._data.GetValue().strip()
        try:
            v = base64.urlsafe_b64decode(v)
            v = msgpack_loads(v)
        except Exception:
            return  # TODO: feedback info to the UI
        if (
            isinstance(v, dict)
            and isinstance(room_id := v.get("id"), str)
            and isinstance(block_names := v.get("block_names"), list)
            and room_id
            and block_names
            and all(isinstance(block_name, str) and block_name for block_name in block_names)
        ):
            return room_id, block_names
