import asyncio
import webbrowser
from typing import Any

from prompt_toolkit import HTML
from prompt_toolkit.application import get_app
from prompt_toolkit.formatted_text import AnyFormattedText, FormattedText
from prompt_toolkit.layout import AnyContainer, HSplit, VSplit, Window, WindowAlign
from prompt_toolkit.layout.dimension import D
from prompt_toolkit.mouse_events import MouseEvent, MouseEventType
from prompt_toolkit.widgets import Dialog, Frame, Label, RadioList, TextArea

from .extras import EasternButton
from .settings import Settings


class BasicDialog:
    def __init__(self, title: AnyFormattedText = "", modal=True):
        self.future = asyncio.Future()
        self.dialog = Dialog(
            body=self.create_body(),
            title=title,
            buttons=self.create_buttons(),
            modal=modal,
            width=D(preferred=80),
        )

    def set_done(self, result: Any = True):
        self.future.set_result(result)

    def create_body(self) -> AnyContainer:
        return HSplit([Label(text=Settings.gettext("basic_dialog"))])

    def create_buttons(self):
        ok_button = EasternButton(
            text=Settings.gettext("ok"), handler=(lambda: self.set_done())
        )
        return [ok_button]

    def set_exception(self, exc):
        self.future.set_exception(exc)

    def __pt_container__(self):
        return self.dialog


class MessageDialog(BasicDialog):
    def __init__(self, title="", message="", modal=True):
        self.message = message
        super().__init__(title, modal)

    def create_body(self) -> AnyContainer:
        return HSplit([Label(text=self.message)])


class QueryDialog(BasicDialog):
    def __init__(
        self, title: AnyFormattedText = "", message: AnyFormattedText = "", modal=True
    ):
        self.message = message
        super().__init__(title, modal)

    def create_body(self) -> AnyContainer:
        return HSplit([Label(text=self.message)])

    def create_buttons(self):
        ok_button = EasternButton(
            text=Settings.gettext("ok"), handler=(lambda: self.set_done(True))
        )
        cancel_button = EasternButton(
            text=Settings.gettext("cancel"), handler=(lambda: self.set_done(False))
        )
        return [ok_button, cancel_button]


class WelcomeDialog(BasicDialog):
    def __init__(self, modal=True):
        self.website = FormattedText(
            [
                ("", f"{Settings.gettext('visit')} "),
                # ('class:b', 'GitHub:'),
                ("", Settings.__website__, self.open_url),
                ("", f" {Settings.gettext('displayhelp')}"),
            ]
        )
        super().__init__("PYMUD", modal)

    def open_url(self, event: MouseEvent):
        if event.event_type == MouseEventType.MOUSE_UP:
            webbrowser.open(Settings.__website__)

    def create_body(self) -> AnyContainer:
        import platform
        import sys

        body = HSplit(
            [
                Window(height=1),
                Label(
                    HTML(
                        Settings.gettext(
                            "appinfo", Settings.__version__, Settings.__release__
                        )
                    ),
                    align=WindowAlign.CENTER,
                ),
                Label(
                    HTML(
                        Settings.gettext(
                            "author", Settings.__author__, Settings.__email__
                        )
                    ),
                    align=WindowAlign.CENTER,
                ),
                Label(self.website, align=WindowAlign.CENTER),
                Label(
                    Settings.gettext(
                        "sysversion",
                        platform.system(),
                        platform.version(),
                        platform.python_version(),
                    ),
                    align=WindowAlign.CENTER,
                ),
                Window(height=1),
            ]
        )

        return body


class NewSessionDialog(BasicDialog):
    def __init__(self):
        super().__init__(Settings.gettext("new_session"), True)

    def create_body(self) -> AnyContainer:
        body = HSplit(
            [
                VSplit(
                    [
                        HSplit(
                            [
                                Label(f" {Settings.gettext('sessionname')}:"),
                                Frame(
                                    body=TextArea(
                                        name="session",
                                        text="session",
                                        multiline=False,
                                        wrap_lines=False,
                                        height=1,
                                        dont_extend_height=True,
                                        width=D(preferred=10),
                                        focus_on_click=True,
                                        read_only=False,
                                    ),
                                ),
                            ]
                        ),
                        HSplit(
                            [
                                Label(f" {Settings.gettext('host')}:"),
                                Frame(
                                    body=TextArea(
                                        name="host",
                                        text="mud.pkuxkx.net",
                                        multiline=False,
                                        wrap_lines=False,
                                        height=1,
                                        dont_extend_height=True,
                                        width=D(preferred=20),
                                        focus_on_click=True,
                                        read_only=False,
                                    ),
                                ),
                            ]
                        ),
                        HSplit(
                            [
                                Label(f" {Settings.gettext('port')}:"),
                                Frame(
                                    body=TextArea(
                                        name="port",
                                        text="8081",
                                        multiline=False,
                                        wrap_lines=False,
                                        height=1,
                                        dont_extend_height=True,
                                        width=D(max=8),
                                        focus_on_click=True,
                                        read_only=False,
                                    ),
                                ),
                            ]
                        ),
                        HSplit(
                            [
                                Label(f" {Settings.gettext('encoding')}:"),
                                Frame(
                                    body=TextArea(
                                        name="encoding",
                                        text="utf8",
                                        multiline=False,
                                        wrap_lines=False,
                                        height=1,
                                        dont_extend_height=True,
                                        width=D(max=8),
                                        focus_on_click=True,
                                        read_only=False,
                                    ),
                                ),
                            ]
                        ),
                    ]
                )
            ]
        )

        return body

    def create_buttons(self):
        ok_button = EasternButton(
            text=Settings.gettext("ok"), handler=self.btn_ok_clicked
        )
        cancel_button = EasternButton(
            text=Settings.gettext("cancel"), handler=(lambda: self.set_done(False))
        )
        return [ok_button, cancel_button]

    def btn_ok_clicked(self):
        def get_text_safely(buffer_name):
            buffer = get_app().layout.get_buffer_by_name(buffer_name)
            return buffer.text if buffer else ""

        name = get_text_safely("session")
        host = get_text_safely("host")
        port = get_text_safely("port")
        encoding = get_text_safely("encoding")
        result = (name, host, port, encoding)
        self.set_done(result)


class LogSelectionDialog(BasicDialog):
    def __init__(self, text, values, modal=True):
        self._header_text = text
        self._selection_values = values
        self._itemsCount = len(values)
        if len(values) > 0:
            self._radio_list = RadioList(values=self._selection_values)
        else:
            self._radio_list = Label(Settings.gettext("nolog").center(13))
        super().__init__(Settings.gettext("chooselog"), modal)

    def create_body(self) -> AnyContainer:
        body = HSplit(
            [Label(text=self._header_text, dont_extend_height=True), self._radio_list]
        )
        return body

    def create_buttons(self):
        ok_button = EasternButton(
            text=Settings.gettext("ok"), handler=self.btn_ok_clicked
        )
        cancel_button = EasternButton(
            text=Settings.gettext("cancel"), handler=(lambda: self.set_done(False))
        )
        return [ok_button, cancel_button]

    def btn_ok_clicked(self):
        if self._itemsCount:
            if isinstance(self._radio_list, RadioList):
                result = self._radio_list.current_value
            else:
                result = None
            self.set_done(result)
        else:
            self.set_done(False)
