from typing import Dict, List, Literal, Optional, Tuple, Union

from pydantic import BaseModel, Extra, Field

from .api import Snowflake


class Intents(BaseModel):
    guilds: bool = True
    guild_members: bool = False
    guild_moderation: bool = True
    guild_emojis_and_stickers: bool = True
    guild_integrations: bool = True
    guild_webhooks: bool = True
    guild_invites: bool = True
    guild_voice_states: bool = True
    guild_presences: bool = False
    guild_messages: bool = True
    guild_message_reactions: bool = True
    guild_message_typing: bool = True
    direct_messages: bool = True
    direct_message_reactions: bool = True
    direct_message_typing: bool = True
    message_content: bool = False
    guild_scheduled_events: bool = True
    auto_moderation_configuration: bool = True
    auto_moderation_execution: bool = True

    def to_int(self):
        return (
            self.guilds << 0
            | self.guild_members << 1
            | self.guild_moderation << 2
            | self.guild_emojis_and_stickers << 3
            | self.guild_integrations << 4
            | self.guild_webhooks << 5
            | self.guild_invites << 6
            | self.guild_voice_states << 7
            | self.guild_presences << 8
            | self.guild_messages << 9
            | self.guild_message_reactions << 10
            | self.guild_message_typing << 11
            | self.direct_messages << 12
            | self.direct_message_reactions << 13
            | self.direct_message_typing << 14
            | self.message_content << 15
            | self.guild_scheduled_events << 16
            | self.auto_moderation_configuration << 20
            | self.auto_moderation_execution << 21
        )


class BotInfo(BaseModel):
    token: str
    shard: Optional[Tuple[int, int]] = None
    intent: Intents = Field(default_factory=Intents)
    application_commands: Dict[str, List[Union[Snowflake, Literal["*"]]]] = Field(
        default_factory=dict
    )


class Config(BaseModel, extra=Extra.ignore):
    discord_bots: List[BotInfo] = Field(default_factory=list)
    discord_compress: bool = False
    discord_api_version: int = 10
    discord_api_timeout: float = 30.0
    discord_handle_self_message: bool = False
    discord_proxy: Optional[str] = None
