"""
Defines the data-forms Tab
"""

import logging
from typing import Any, Callable, TYPE_CHECKING, Concatenate, ParamSpec

from poezio import windows
from poezio.tabs import Tab, NoInputTab
from poezio.core.structs import Command
from slixmpp.plugins.xep_0004 import Form

if TYPE_CHECKING:
    from poezio.core.core import Core

log = logging.getLogger(__name__)

P = ParamSpec('P')


class DataFormsTab(NoInputTab):
    """
    A tab containing various window type, displaying
    a form that the user needs to fill.
    """
    plugin_commands: dict[str, Command] = {}
    plugin_keys: dict[str, Callable[..., Any]] = {}

    def __init__(self, core: 'Core', form: Form, on_cancel: Callable[Concatenate[Form, P], None], on_send: Callable[Concatenate[Form, P], None], *args: P.args, **kwargs: P.kwargs) -> None:
        NoInputTab.__init__(self, core)
        self._form = form
        self._on_cancel = on_cancel
        self._on_send = on_send
        self._args = args
        self._kwargs = kwargs
        self.fields = []
        for field in self._form:
            self.fields.append(field)
        self.topic_win = windows.Topic()
        self.form_win = windows.FormWin(form, self.height - 4, self.width, 1,
                                        0)
        self.help_win = windows.HelpText("Ctrl+Y: send form, Ctrl+G: cancel")
        self.help_win_dyn = windows.HelpText()
        self.key_func['KEY_UP'] = self.form_win.go_to_previous_input
        self.key_func['KEY_DOWN'] = self.form_win.go_to_next_input
        self.key_func['^G'] = self.on_cancel
        self.key_func['^Y'] = self.on_send
        self.resize()
        self.update_commands()

    def on_cancel(self) -> bool:
        self._on_cancel(self._form, *self._args, **self._kwargs)
        return True

    def on_send(self) -> bool:
        self._form.reply()
        self.form_win.reply()
        self._on_send(self._form, *self._args, **self._kwargs)
        return True

    def on_input(self, key: str, raw: bool = False) -> None:
        if key in self.key_func:
            res = self.key_func[key]()
            if res:
                return
            self.help_win_dyn.refresh_txt(self.form_win.get_help_message())
            self.form_win.refresh_current_input()
        else:
            self.form_win.on_input(key, raw=raw)

    def resize(self) -> None:
        self.need_resize = False
        self.topic_win.resize(1, self.width, 0, 0)
        self.form_win.resize(self.height - 3 - Tab.tab_win_height(),
                             self.width, 1, 0)
        self.help_win.resize(1, self.width, self.height - 1, 0)
        self.help_win_dyn.resize(1, self.width,
                                 self.height - 2 - Tab.tab_win_height(), 0)

    def refresh(self) -> None:
        if self.need_resize:
            self.resize()
        self.topic_win.refresh(self._form['title'])
        self.refresh_tab_win()
        self.help_win.refresh()
        self.help_win_dyn.refresh_txt(self.form_win.get_help_message())
        self.form_win.refresh()
