import sys
import time
from typing import Never, Optional

import scrap_engine as se

from pokete.base.context import Context
from pokete.base.ui.elements.labels import CloseLabel
from pokete.base.ui.notify import notifier
from pokete.base.ui.views.boxes import InfoBoxView
from pokete.base.ui.views.choose_box import ChooseBoxView
from pokete.release import SPEED_OF_TIME

from .achievements import AchievementOverview
from .audio import audio
from .game import ReturnToMenuException
from .mods import ModInfo
from .save import save
from .settings import Slider, TextInputBox, VisSetting, settings
from .side_loops import About


class Menu(ChooseBoxView):
    def __init__(self):
        super().__init__(50, 35, "Menu", [CloseLabel(),])
        self.playername_input = TextInputBox("Playername:", 17)
        self.represent_char_input = TextInputBox("Char:", 1)
        self.mods_label = se.Text("Mods", state="float")
        self.ach_label = se.Text("Achievements", state="float")
        self.about_label = se.Text("About", state="float")
        self.save_label = se.Text("Save", state="float")
        self.exit_label = se.Text("Exit", state="float")
        self.return_label = se.Text("Return to main menu", state="float")
        self.elems = [
            self.playername_input,
            self.represent_char_input,
            VisSetting("Autosave", "autosave", {True: "On", False: "Off"}),
            VisSetting("Animations", "animations", {True: "On", False: "Off"}),
            VisSetting("Save trainers", "save_trainers", {True: "On", False: "Off"}),
            VisSetting("Audio", "audio", {True: "On", False: "Off"}),
            Slider("Volume", "volume"),
            VisSetting("Load mods", "load_mods", {True: "On", False: "Off"}),
            self.mods_label,
            self.ach_label,
            self.about_label,
            self.save_label,
            self.return_label,
            self.exit_label,
        ]

    def new_size(self) -> tuple[int, int]:
        return self.map.height - 3, 35

    def choose(self, ctx: Context, idx: int) -> Optional[Never]:
        i = self.c_obs[self.index.index]
        audio_before = settings("audio").val
        volume_before = settings("volume").val
        if i == self.playername_input:
            name = self.playername_input(ctx)
            if name is not None:
                ctx.figure.name = name
                self.map.name_label_rechar(ctx.figure.name)
        elif i == self.represent_char_input:
            inp = self.represent_char_input(ctx)
            if inp is None:
                return
            # excludes bad unicode:
            if len(inp.encode("utf-8")) != 1 and inp not in [
                "ä",
                "ö",
                "ü",
                "ß",
            ]:
                inp = ctx.figure.char
                self.represent_char_input.set_value(inp)
                notifier.notify(
                    "Error",
                    "Bad character",
                    "The chosen character has to be a \
valid single-space character!",
                )
                return
            self.represent_char_input.set_value(inp)
            ctx.figure.rechar(inp)
        elif i == self.mods_label:
            ModInfo()(ctx)
        elif i == self.save_label:
            # When will python3.10 come out?
            with InfoBoxView(
                "Saving....",
                info=None,
                ctx=ctx,
            ):
                # Shows a box displaying "Saving...." while saving
                save(ctx.figure)
                time.sleep(SPEED_OF_TIME * 1.5)
        elif i == self.exit_label:
            save(ctx.figure)
            sys.exit()
        elif i == self.about_label:
            About()(ctx)
        elif i == self.ach_label:
            AchievementOverview()(ctx)
        elif i == self.return_label:
            save(ctx.figure)
            raise ReturnToMenuException()
        elif isinstance(i, VisSetting) or isinstance(i, Slider):
            i.change(ctx)
        if (
            audio_before != settings("audio").val
            or volume_before != settings("volume").val
        ):
            audio.play(ctx.figure.map.song)

    def __call__(self, ctx: Context):
        """Opens the dex"""
        self.resize(ctx.map.height - 3, 35)
        self.playername_input.set_value(ctx.figure.name)
        self.represent_char_input.set_value(ctx.figure.char)
        self.add_elems()
        with self.add(ctx.map, ctx.map.width - self.width, 0):
            return super().__call__(ctx)
