import datetime
from typing import Any, List, Optional, Tuple, Union

import discord.abc

from .activity import BaseActivity, Spotify
from .asset import Asset
from .channel import DMChannel, GroupChannel, VoiceChannel
from .colour import Colour
from .enums import DefaultAvatar, Status
from .flags import PublicUserFlags
from .guild import Guild
from .message import Message
from .permissions import Permissions
from .relationship import Relationship
from .role import Role
from .user import Profile, User

class VoiceState:
    deaf: bool
    mute: bool
    self_mute: bool
    self_deaf: bool
    self_stream: bool
    self_video: bool
    afk: bool
    channel: Optional[Union[GroupChannel, VoiceChannel]]
    session_id: str

class Member(discord.abc.Messageable, discord.abc.User):
    joined_at: Optional[datetime.datetime]
    activities: Tuple[Union[BaseActivity, Spotify], ...]
    nick: Optional[str]
    premium_since: Optional[datetime.datetime]
    guild: Guild

    # From discord.user.BaseUser
    name: str
    id: int
    discriminator: str
    avatar: Optional[str]
    bot: bool
    system: bool
    @property
    def public_flags(self) -> PublicUserFlags: ...
    @property
    def avatar_url(self) -> Asset: ...
    def is_avatar_animated(self) -> bool: ...
    def avatar_url_as(
        self, *, format: Optional[str] = ..., static_format: str = ..., size: int = ...
    ) -> Asset: ...
    @property
    def default_avatar(self) -> DefaultAvatar: ...
    @property
    def default_avatar_url(self) -> Asset: ...
    # End from discord.user.BaseUser

    # From discord.user.User
    @property
    def created_at(self) -> datetime.datetime: ...
    @property
    def dm_channel(self) -> Optional[DMChannel]: ...
    async def create_dm(self) -> DMChannel: ...
    @property
    def relationship(self) -> Optional[Relationship]: ...
    async def mutual_friends(self) -> List[User]: ...
    def is_friend(self) -> bool: ...
    def is_blocked(self) -> bool: ...
    async def block(self) -> None: ...
    async def unblock(self) -> None: ...
    async def remove_friend(self) -> None: ...
    async def send_friend_request(self) -> None: ...
    async def profile(self) -> Profile: ...
    # End from discord.user.User
    def __eq__(self, other: Any) -> bool: ...
    def __ne__(self, other: Any) -> bool: ...
    def __hash__(self) -> int: ...
    @property
    def status(self) -> Union[Status, str]: ...
    @property
    def raw_status(self) -> str: ...
    @property
    def mobile_status(self) -> Status: ...
    @property
    def desktop_status(self) -> Status: ...
    @property
    def web_status(self) -> Status: ...
    def is_on_mobile(self) -> bool: ...
    @property
    def colour(self) -> Colour: ...
    @property
    def color(self) -> Colour: ...
    @property
    def roles(self) -> List[Role]: ...
    @property
    def mention(self) -> str: ...
    @property
    def display_name(self) -> str: ...
    @property
    def activity(self) -> Union[BaseActivity, Spotify]: ...
    def mentioned_in(self, message: Message) -> bool: ...
    def permissions_in(self, channel: discord.abc.GuildChannel) -> Permissions: ...
    @property
    def top_role(self) -> Role: ...
    @property
    def guild_permissions(self) -> Permissions: ...
    @property
    def voice(self) -> Optional[VoiceState]: ...
    async def ban(
        self, *, reason: Optional[str] = ..., delete_message_days: int = ...
    ) -> None: ...
    async def unban(self, *, reason: Optional[str] = ...) -> None: ...
    async def kick(self, *, reason: Optional[str] = ...) -> None: ...
    async def edit(
        self,
        *,
        reason: Optional[str] = ...,
        nick: Optional[str] = ...,
        mute: bool = ...,
        deafen: bool = ...,
        roles: List[Role] = ...,
        voice_channel: Optional[VoiceChannel] = ...,
    ) -> None: ...
    async def move_to(
        self, channel: Optional[VoiceChannel], *, reason: Optional[str] = ...
    ) -> None: ...
    async def add_roles(
        self,
        *roles: discord.abc.Snowflake,
        reason: Optional[str] = ...,
        atomic: bool = ...,
    ) -> None: ...
    async def remove_roles(
        self,
        *roles: discord.abc.Snowflake,
        reason: Optional[str] = ...,
        atomic: bool = ...,
    ) -> None: ...
