"""
Navigation menu components typically used in sidebars or dropdowns.
"""
from .base import Component
from typing import List, Optional

import logging

logger = logging.getLogger(__name__)


class Menu(Component):
    """A vertical navigation menu container."""
    def __init__(
        self,
        children: List[Component],
        back: Optional[Component] = None,
        title: Optional[str] = None,
        **kwargs,
    ):
        super().__init__(
            **kwargs,
            children=(children or []) + ([back] if back else []),
        )
        self.main_content = children or []
        self.back = back
        self.title = title

    def get_title(self, **kwargs) -> Optional[str]:
        if self.title is None:
            return None

        if isinstance(self.title, str):
            return self.title

        if hasattr(self.title, "__call__"):
            return self.title(kwargs[self.key])

        return self.title

    def render_back(self, **kwargs) -> str:
        if self.back is None:
            return ""
        url = self.back.get_url(**kwargs)
        title = self.back.get_title(**kwargs)
        return f"""
            <li>
                <a href="{url}" class="btn btn-sm mb-2"
                    hx-get="{url}"
                    hx-target="#app-layout"
                    hx-swap="morph">
                    {{% heroicon_mini "arrow-left" %}}
                    {title}
                </a>
            </li>"""

    def render_html(self, **kwargs) -> str:
        title = self.get_title(**kwargs)
        return f"""
        <ul id="{self.uid}" class="menu w-full wrap-anywhere {self.classes}">
            {self.render_back(**kwargs)}
            {f'<li class="menu-title font-semibold text-base-content/70">{title}</li>' if title else ""}
            {"".join([child.render(**kwargs) for child in self.main_content])}
        </ul>
        """


class MenuItem(Component):
    """A clickable item within a Menu."""
    def __init__(
        self, title: str, active: bool = False, icon: Optional[str] = None, **kwargs
    ):
        super().__init__(**kwargs)
        self.title = title
        self.active = active
        self.icon = icon

    def get_title(self, **kwargs) -> str:
        if isinstance(self.title, str):
            return self.title

        if hasattr(self.title, "__call__"):
            return self.title(kwargs[self.key])

        return self.title

    def render_icon(self) -> str:
        if self.icon:
            return f'{{% heroicon_mini "{self.icon}" %}}'
        return ""

    def render_html(self, **kwargs) -> str:
        url = self.get_url(**kwargs)
        title = self.get_title(**kwargs)

        return f"""
            <li id="{self.uid}">
                <a href="{url}"{" class='menu-active'" if self.active else ""}
                    hx-get="{url}"
                    hx-swap="morph"
                    hx-target="#app-layout"
                >
                    {self.render_icon()}
                    {title}
                </a>
            </li>"""


class MenuItemDropdown(Component):
    """A collapsible dropdown item within a Menu."""
    def __init__(
        self, title: str, open: bool = False, icon: Optional[str] = None, **kwargs
    ):
        super().__init__(**kwargs)
        self.title = title
        self.open = open
        self.icon = icon

    def get_title(self, **kwargs) -> str:
        if isinstance(self.title, str):
            return self.title

        if hasattr(self.title, "__call__"):
            return self.title(kwargs[self.key])

        return self.title

    def render_icon(self) -> str:
        if self.icon:
            return f'{{% heroicon_mini "{self.icon}" %}}'
        return ""

    def render_html(self, **kwargs) -> str:
        title = self.get_title()
        return f"""
            <li id="{self.uid}">
                <details {"open" if self.open else ""}>
                    <summary>
                        {self.render_icon()}
                        {title}
                    </summary>
                        {"\n".join([child.render(**kwargs) for child in self.children])}
                </details>
            </li>"""
