from __future__ import annotations

import typing as t

import attr
import hikari

from arc.abc.option import CommandOptionBase, OptionParams, OptionType
from arc.internal.types import ClientT

if t.TYPE_CHECKING:
    import typing_extensions as te

__all__ = ("ChannelOption", "ChannelParams")


@t.final
class ChannelParams(OptionParams[hikari.PartialChannel]):
    """The parameters for a channel option.
    The channel types are inferred from the type hint.

    !!! example
        An option of type `hikari.TextableGuildChannel` will resolve to `hikari.ChannelType.GUILD_PUBLIC_THREAD |
        hikari.ChannelType.GUILD_PRIVATE_THREAD |
        hikari.ChannelType.GUILD_NEWS_THREAD`.

    Parameters
    ----------
    description : str
        The description of the option
    name : str
        The name of the option. If not provided, the name of the parameter will be used.
    name_localizations : Mapping[hikari.Locale, str]
        The name of the option in different locales
    description_localizations : Mapping[hikari.Locale, str]
        The description of the option in different locales
    """

    __slots__: t.Sequence[str] = ()


@attr.define(slots=True, kw_only=True)
class ChannelOption(CommandOptionBase[hikari.PartialChannel, ClientT, ChannelParams]):
    """A slash command option that represents a channel.

    ??? hint
        To add an option of this type to your command, add an argument to your command function with the following type hint:
        ```py
        opt_name: arc.Option[hikari.TextableGuildChannel, ChannelParams(...)]
        ```

        **Note:** The type of the channel determines the channel types that this option can be used with.
    """

    channel_types: t.Sequence[hikari.ChannelType] | None = None
    """The channel types that the option can be."""

    @property
    def option_type(self) -> OptionType:
        return OptionType.CHANNEL

    @classmethod
    def _from_params(
        cls, *, name: str, arg_name: str, is_required: bool, params: ChannelParams, **kwargs: t.Any
    ) -> te.Self:
        channel_types = kwargs.pop("channel_types")
        return cls(
            name=name,
            arg_name=arg_name,
            description=params.description,
            is_required=is_required,
            name_localizations=params.name_localizations,
            description_localizations=params.description_localizations,
            channel_types=channel_types,
            **kwargs,
        )

    def _to_dict(self) -> dict[str, t.Any]:
        return {**super()._to_dict(), "channel_types": self.channel_types or None}


# MIT License
#
# Copyright (c) 2023-present hypergonial
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
