"""For managing the gateway"""

import json
from enum import IntEnum, Flag
from dataclasses import InitVar, dataclass


GATEWAY_VERSION = 9

class GATEWAY_OPCODES(IntEnum):
    DISPATCH = 0
    HEARTBEAT = 1
    IDENTIFY = 2
    PRESENCE_UPDATE = 3
    VOICE_STATE_UPDATE = 4
    RESUME = 6
    RECONNECT = 7
    REQUEST_GUILD_MEMBERS = 8
    INVALID_SESSION = 9
    HELLO = 10
    HEARTBEAT_ACK = 11

class GATEWAY_CLOSE_CODES(IntEnum):
    UNKNOWN_ERROR = 4000
    UNKNOWN_OPCODE = 4001
    DECODE_ERROR = 4002
    NOT_AUTHENTICATED = 4003
    AUTHENTICATION_FAILED = 4004
    ALREADY_AUTHENTICATED = 4005
    INVALID_SEQ = 4007
    RATE_LIMITED = 4008
    SESSION_TIMED_OUT = 4009
    INVALID_SHARD = 4010
    SHARDING_REQUIRED = 4011
    INVALID_API_VERSION = 4012
    INVALID_INTENTS = 4013
    DISALLOWED_INTENTS = 4014

class VOICE_OPCODES(IntEnum):
    IDENTIFY = 0
    SELECT_PROTOCOL = 1
    READY = 2
    HEARTBEAT = 3
    SESSION_DESCRIPTION = 4
    SPEAKING = 5
    HEARTBEAT_ACK = 6
    RESUME = 7
    HELLO = 8
    RESUMED = 9
    CLIENT_DISCONNECT = 10

class VOICE_CLOSE_EVENT_CODES(IntEnum):
    UNKNOWN_OPCODE = 4001
    DECODE_FAILED = 4002
    NOT_AUTHENTICATED = 4003
    AUTHENTICATION_FAILED = 4004
    ALREADY_AUTHENTICATED = 4005
    INVALID_SESSION = 4006
    SESSION_TIMEOUT = 4009
    SERVER_NOT_FOUND = 4011
    UNKNOWN_PROTOCOL = 4012
    DISCONNECTED = 4014
    VOICE_SERVER_CRASHED = 4015
    UNKNOWN_ENCRYPTION_MODE = 4016

class JSON_CODES(IntEnum):
    GENERAL_ERROR = 0
    UNKNOWN_ACCOUNT = 10001
    UNKNOWN_APPLICATION = 10002
    UNKNOWN_CHANNEL = 10003
    UNKNOWN_GUILD = 10004
    UNKNOWN_INTEGRATION = 10005
    UNKNOWN_INVITE = 10006
    UNKNOWN_MEMBER = 10007
    UNKNOWN_MESSAGE = 10008
    UNKNOWN_OVERWRITE = 10009
    UNKNOWN_PROVIDER = 10010
    UNKNOWN_ROLE = 10011
    UNKNOWN_TOKEN = 10012
    UNKNOWN_USER = 10013
    UNKNOWN_EMOJI = 10014
    UNKNOWN_WEBHOOK = 10015
    UNKNOWN_WEBHOOK_SERVICE = 10016
    UNKNOWN_SESSION = 10020
    UNKNOWN_BAN = 10026
    UNKNOWN_SKU = 10027
    UNKNOWN_STORE_LISTING = 10028
    UNKNOWN_ENTITLEMENT = 10029
    UNKNOWN_BUILD = 10030
    UNKNOWN_LOBBY = 10031
    UNKNOWN_BRANCH = 10032
    UNKNOWN_STORE_DIRECTORY_LAYOUT = 10033
    UNKNOWN_REDISTRIBUTABLE = 10036
    UNKNOWN_GIFT_CODE = 10038
    UNKNOWN_STREAM = 10049
    UNKNOWN_PREM_SERV_SUB_COOLDOWN = 10050
    UNKNOWN_GUILD_TEMPLATE = 10057
    UNKNOWN_DISCOVERABLE_SERVER_CATEGORY = 10059
    UNKNOWN_STICKER = 10060
    UNKNOWN_INTERACTION = 10062
    UNKNOWN_APP_COMMAND = 10063
    UNKNOWN_APP_COMMAND_PERM = 10066
    UNKNOWN_STAGE_INSTANCE = 10067
    UNKNOWN_GUILD_MEMBER_VERIFICATION_FORM = 10068
    UNKNOWN_GUILD_WELCOME_SCREEN = 10069
    UNKNOWN_GUILD_SCHEDULED_EVENT = 10070
    UNKNOWN_GUILD_SCHEDULED_EVENT_USER = 10071
    BOTS_UNALLOWED_ENDPOINT = 20001
    BOTS_ONLY_ENDPOINT = 20002
    EXPLICIT_CONTENT_UNALLOWED_USER = 20009
    UNAUTHORIZED_APP_ACTION = 20012
    UNAUTHORIZED_APP_ACTION_SLOWMODE = 20016
    ACCOUNT_OWNER_ONLY_ACTION = 20018
    MESSAGE_EDIT_UNALLOWED_ANNOUNCEMENT_RATE_LIMIT = 20022
    CHANNEL_WRITE_RATE_LIMIT = 20028
    WRITE_ACTION_SERVER_RATE_LIMIT = 20029
    UNALLOWED_WORDS_SERVER_DETAILS = 20031
    GUILD_PREMIUM_LEVEL_TOO_LOW = 20035
    MAX_GUILDS_REACHED = 30001
    MAX_FRIENDS_REACHED = 30002
    MAX_CHANNEL_PINS_REACHED = 30003
    MAX_RECIPIENTS_REACHED = 30004
    MAX_GUILD_ROLES_REACHED = 30005
    MAX_WEBHOOKS_REACHED = 30007
    MAX_EMOJIS_PER_GUILD_REACHED = 30008
    MAX_REACTIONS_PER_USER_REACHED = 30010
    MAX_GUILD_CHANNELS_REACHED = 30013
    MAX_MESSAGE_ATTACHMENTS_REACHED = 30015
    MAX_INVITES_REACHED = 30016
    MAX_ANIMATED_EMOJIS_REACHED = 30018
    MAX_SERVER_MEMBERS_REACHED = 30019
    MAX_SERVER_CATEGORIES_REACHED = 30030
    GUILD_HAS_TEMPLATE = 30031
    MAX_THREAD_PARTICIPANTS_REACHED = 30033
    MAX_NON_MEMBER_BANS_REACHED = 30035
    MAX_BAN_FETCHES_REACHED = 30037
    MAX_UNCOMPLETED_GUILD_EVENTS_REACHED = 30038
    MAX_STICKERS_REACHED = 30039
    MAX_PRUNE_REQUESTS_REACHED = 30040
    MAX_GUILD_WIDGET_EDITS_REACHED = 30042
    MAX_EDITS_OLD_MESSAGES_REACHED = 30046
    UNAUTHORIZED = 40001
    ACCOUNT_VERIFICATION_NEEDED = 40002
    OPENING_DM_TOO_FAST = 40003
    SEND_MESSAGES_TEMPORARILY_DISABLED = 40004
    REQUEST_ENTITY_TOO_LARGE = 40005
    FEATURE_DISABLED_SERVER_SIDE = 40006
    USER_BANNED_FROM_GUILD = 40007
    TARGET_NOT_CONNECTED_TOO_VOICE = 40032
    MESSAGE_ALREADY_CROSSPOSTED = 40033
    APP_COMMAND_NAME_ALREADY_EXISTS = 40041
    MISSING_ACCESS = 50001
    INVALID_ACCOUNT_TYPE = 50002
    CANNOT_EXECUTE_ON_DM = 50003
    GUILD_WIDGET_DISABLED = 50004
    CANNOT_EDIT_MESSAGE_BY_OTHER_USER = 50005
    CANNOT_SEND_EMPTY_MESSAGE = 50006
    CANNOT_MESSAGE_USER = 50007
    CANNOT_SEND_MESSAGE_IN_VOICE_CHANNEL = 50008
    CHANNEL_VERIFICATION_LEVEL_TOO_HIGH = 50009
    OAUTH2_APP_NO_BOT = 50010
    OAUTH2_APP_LIMIT_REACHED = 50011
    INVALID_OAUTH2_STATE = 50012
    MISSING_ACTION_PERMISSIONS = 50013
    NOTE_TOO_LONG = 50015
    TOO_FEW_TOO_MANY_MESSAGES_TO_DELETE = 50016
    MESSAGE_PIN_TO_SENT_CHANNEL = 50019
    INVITE_CODE_INVALID_OR_TAKEN = 50020
    CANNOT_EXECUTE_ACTION_ON_SYSTEM_MESSAGE = 50021
    CANNOT_EXECUTE_ACTION_ON_CHANNEL_TYPE = 50024
    INVALID_OAUTH2_TOKEN = 50025
    MISSING_OAUTH2_SCOPE = 50026
    INVALID_WEBHOOK_TOKEN = 50027
    INVALID_ROLE = 50028
    INVALID_RECIPIENTS = 50029
    MESSAGE_TOO_OLD_FOR_BULK_DELETE = 50034
    INVALID_FORM_BODY_FORM_TYPE = 50035
    INVITE_ACCEPTED_WHERE_BOT_NOT_PRESENT = 50036
    INVALID_API_VERSION = 50041
    FILE_UPLOAD_EXCEEDS_MAX_SIZE = 50045
    INVALID_FILE_UPLOAD = 50046
    CANNOT_SELF_REDEEM_GIFT_CODE = 50054
    INVALID_GUILD = 50055
    INVALID_MESSAGE_TYPE = 50068
    PAYMENT_SOURCE_REQUIRED_FOR_REDEEM = 50070
    CANNOT_DELETE_COMMUNITY_GUILD_REQUIRED_CHANNEL = 50074
    INVALID_STICKER_SENT = 50081
    INVALID_THREAD_NOTIFICATION_SETTINGS = 50084
    BEFORE_PREDATES_THREAD_DATE = 50085
    COMMUNITY_SERVER_CHANNELS_TEXT_ONLY = 50086
    SERVER_UNAVAILABLE_IN_LOCATION = 50095
    SERVER_MONETIZATION_REQUIRED = 50097
    SERVER_REQUIRES_MORE_BOOST = 50101
    INVALID_JSON = 50109
    TWO_FACTOR_AUTH_REQUIRED = 60003
    NO_USER_WITH_DISCORDTAG_FOUND = 80004
    REACTION_BLOCKED = 90001
    API_RESOURCES_OVERLOADED = 130000
    STAGE_ALREADY_OPENED = 150006
    REPLY_WITHOUT_MESSAGE_READ_PERM_ALLOWED = 160002
    THREAD_FOR_MESSAGE_ALREADY_CREATED = 160004
    THREAD_LOCKED = 160005
    MAX_ACTIVE_THREADS_REACHED = 160006
    MAX_ACTIVE_ANNOUNCEMENT_THREADS_REACHED = 160007
    INVALID_LOTTIE_FILE_JSON = 170001
    LOTTIE_CANNOT_CONTAIN_RASTERIZED_IMAGE = 170002
    STICKER_MAX_FRAMERATE_REACHED = 170003
    STICKER_MAX_FRAMES_REACHED = 170004
    LOTTIE_ANIMATION_MAX_DIMENSIONS_REACHED = 170005
    STICKER_FRAME_RATE_TOO_SMALL_TOO_LARGE = 170006
    STICKER_MAX_DURATION_EXCEEDED = 170007
    CANNOT_UPDATE_FINISHED_EVENT = 180000
    STAGE_EVENT_STAGE_CREATION_FAILED = 180002

class RPC_ERROR_CODES(IntEnum):
    UNKNOWN_ERROR = 1000
    INVALID_PAYLOAD = 4000
    INVALID_COMMAND = 4002
    INVALID_GUILD = 4003
    INVALID_EVENT = 4004
    INVALID_CHANNEL = 4005
    INVALID_PERMISSIONS = 4006
    INVALID_CLIENT_ID = 4007
    INVALID_ORIGIN = 4008
    INVALID_TOKEN = 4009
    INVALID_USER = 4010
    OAUTH2_ERROR = 5000
    SELECT_CHANNEL_TIMEOUT = 5001
    GET_GUILD_TIMEOUT = 5002
    SELECT_VOICE_FORCE_REQUIRED = 5003
    CAPTURE_SHORTCUT_ALREADY_LISTENING = 5004

class RPC_CLOSE_EVENT_CODES(IntEnum):
    INVALID_CLIENT_ID = 4000
    INVALID_ORIGIN = 4001
    RATE_LIMITED = 4002
    TOKEN_REVOKED = 4003
    INVALID_VERSIONING = 4004
    INVALID_ENCODING = 4005

class GATEWAY_INTENTS(Flag):
    GUILDS = 1 << 0
    # GUILD_CREATE
    # GUILD_UPDATE
    # GUILD_DELETE
    # GUILD_ROLE_CREATE
    # GUILD_ROLE_UPDATE
    # GUILD_ROLE_DELETE
    # CHANNEL_CREATE
    # CHANNEL_UPDATE
    # CHANNEL_DELETE
    # CHANNEL_PINS_UPDATE
    # THREAD_CREATE
    # THREAD_UPDATE
    # THREAD_DELETE
    # THREAD_LIST_SYNC
    # THREAD_MEMBER_UPDATE
    # STAGE_INSTANCE_CREATE
    # STAGE_INSTANCE_UPDATE
    # STAGE_INSTANCE_DELETE

    GUILD_MEMBERS = 1 << 1 # privileged
    # GUILD_MEMBER_ADD
    # GUILD_MEMBER_UPDATE
    # GUILD_MEMBER_REMOVE
    # THREAD_MEMBERS_UPDATE

    GUILD_BANS = 1 << 2
    # GUILD_BAN_ADD
    # GUILD_BAN_REMOVE

    GUILD_EMOJIS_AND_STICKERS = 1 << 3
    # GUILD_EMOJIS_UPDATE
    # GUILD_STICKERS_UPDATE

    GUILD_INTEGRATIONS  = 1 << 4
    # GUILD_INTEGRATIONS_UPDATE
    # INTEGRATION_CREATE
    # INTEGRATION_UPDATE
    # INTEGRATION_DELETE

    GUILD_WEBHOOKS = 1 << 5
    # WEBHOOK_UPDATE

    GUILD_INVITES = 1 << 6
    # INVITE_CREATE
    # INVITE_DELETE

    GUILD_VOICE_STATES = 1 << 7
    # VOICE_STATE_UPDATE

    GUILD_PRESENCES = 1 << 8 # privileged
    # PRESENCE_UPDATE

    GUILD_MESSAGES = 1 << 9
    # MESSAGE_CREATE
    # MESSAGE_UPDATE
    # MESSAGE_DELETE
    # MESSAGE_DELETE_BULK

    GUILD_MESSAGE_REACTIONS = 1 << 10
    # MESSAGE_REACTION_ADD
    # MESSAGE_REACTION_REMOVE
    # MESSAGE_REACTION_REMOVE_ALL
    # MESSAGE_REACTION_REMOVE_EMOJI

    GUILD_MESSAGE_TYPING = 1 << 11
    # TYPING_START

    DIRECT_MESSAGES = 1 << 12
    # MESSAGE_CREATE
    # MESSAGE_UPDATE
    # MESSAGE_DELETE
    # CHANNEL_PINS_UPDATE

    DIRECT_MESSAGE_REACTIONS = 1 << 13
    # MESSAGE_REACTION_ADD
    # MESSAGE_REACTION_REMOVE
    # MESSAGE_REACTION_REMOVE_ALL
    # MESSAGE_REACTION_REMOVE_EMOJI

    DIRECT_MESSAGE_TYPING = 1 << 14
    # TYPING_START

    GUILD_SCHEDULED_EVENTS = 1 << 16
    # GUILD_SCHEDULED_EVENT_CREATE
    # GUILD_SCHEDULED_EVENT_UPDATE
    # GUILD_SCHEDULED_EVENT_DELETE
    # GUILD_SCHEDULED_EVENT_USER_ADD
    # GUILD_SCHEDULED_EVENT_USER_REMOVE

    # BASE EVENTS
    # READY
    # RESUMED
    # VOICE_SERVER_UPDATE
    # USER_UPDATE
    # APPLICATION_COMMAND_CREATE
    # APPLICATION_COMMAND_UPDATE
    # APPLICATION_COMMAND_DELETE
    # INTERACTION_CREATE

class Payload:
    __slots__ = ('op', 'd', 's', 't')

    def __init__(self, payload):
        if payload:
            _payload = json.loads(payload) if type(payload) is str else payload
            self.op = _payload['op'] if 'op' in _payload else None
            self.d = _payload['d'] if 'd' in _payload else None
            self.s = _payload['s'] if 's' in _payload else None
            self.t = _payload['t'] if 't' in _payload else None
        else:
            self.op = None
            self.d = None
            self.s = None
            self.t = None
    def __iter__(self):
        yield "op", self.op
        yield "d", self.d
        yield "s", self.s
        yield "t", self.t

    def __repr__(self) -> str:
        _dict = dict(self)
        return json.dumps(_dict)
