use serde_json::Value;

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum DispatchEventType {
    Ready,
    ReadySupplemental,
    Resumed,
    ApplicationCommandPermissionsUpdate,
    AutoModerationRuleCreate,
    AutoModerationRuleUpdate,
    AutoModerationRuleDelete,
    AutoModerationActionExecution,
    ChannelCreate,
    ChannelUpdate,
    ChannelDelete,
    ChannelPinsUpdate,
    ThreadCreate,
    ThreadUpdate,
    ThreadDelete,
    ThreadListSync,
    ThreadMemberUpdate,
    ThreadMembersUpdate,
    EntitlementCreate,
    EntitlementUpdate,
    EntitlementDelete,
    GuildCreate,
    GuildUpdate,
    GuildDelete,
    GuildAuditLogEntryCreate,
    GuildBanAdd,
    GuildBanRemove,
    GuildEmojisUpdate,
    GuildStickersUpdate,
    GuildIntegrationsUpdate,
    GuildMemberAdd,
    GuildMemberRemove,
    GuildMemberUpdate,
    GuildMembersChunk,
    GuildRoleCreate,
    GuildRoleUpdate,
    GuildRoleDelete,
    GuildScheduledEventCreate,
    GuildScheduledEventUpdate,
    GuildScheduledEventDelete,
    GuildScheduledEventUserAdd,
    GuildScheduledEventUserRemove,
    GuildSoundboardSoundCreate,
    GuildSoundboardSoundUpdate,
    GuildSoundboardSoundDelete,
    GuildSoundboardSoundsUpdate,
    IntegrationCreate,
    IntegrationUpdate,
    IntegrationDelete,
    InteractionCreate,
    InviteCreate,
    InviteDelete,
    MessageCreate,
    MessageUpdate,
    MessageDelete,
    MessageDeleteBulk,
    MessageReactionAdd,
    MessageReactionRemove,
    MessageReactionRemoveAll,
    MessageReactionRemoveEmoji,
    MessagePollVoteAdd,
    MessagePollVoteRemove,
    PresenceUpdate,
    PassiveUpdateV1,
    StageInstanceCreate,
    StageInstanceUpdate,
    StageInstanceDelete,
    SubscriptionCreate,
    SubscriptionUpdate,
    SubscriptionDelete,
    TypingStart,
    UserUpdate,
    VoiceChannelEffectSend,
    VoiceStateUpdate,
    VoiceServerUpdate,
    WebhooksUpdate,
    RelationshipAdd,
    RelationshipRemove,
    Unknown(String),
}

impl DispatchEventType {
    pub fn from_event_name(name: &str) -> Self {
        match name {
            "READY" => Self::Ready,
            "READY_SUPPLEMENTAL" => Self::ReadySupplemental,
            "RESUMED" => Self::Resumed,
            "APPLICATION_COMMAND_PERMISSIONS_UPDATE" => Self::ApplicationCommandPermissionsUpdate,
            "AUTO_MODERATION_RULE_CREATE" => Self::AutoModerationRuleCreate,
            "AUTO_MODERATION_RULE_UPDATE" => Self::AutoModerationRuleUpdate,
            "AUTO_MODERATION_RULE_DELETE" => Self::AutoModerationRuleDelete,
            "AUTO_MODERATION_ACTION_EXECUTION" => Self::AutoModerationActionExecution,
            "CHANNEL_CREATE" => Self::ChannelCreate,
            "CHANNEL_UPDATE" => Self::ChannelUpdate,
            "CHANNEL_DELETE" => Self::ChannelDelete,
            "CHANNEL_PINS_UPDATE" => Self::ChannelPinsUpdate,
            "THREAD_CREATE" => Self::ThreadCreate,
            "THREAD_UPDATE" => Self::ThreadUpdate,
            "THREAD_DELETE" => Self::ThreadDelete,
            "THREAD_LIST_SYNC" => Self::ThreadListSync,
            "THREAD_MEMBER_UPDATE" => Self::ThreadMemberUpdate,
            "THREAD_MEMBERS_UPDATE" => Self::ThreadMembersUpdate,
            "ENTITLEMENT_CREATE" => Self::EntitlementCreate,
            "ENTITLEMENT_UPDATE" => Self::EntitlementUpdate,
            "ENTITLEMENT_DELETE" => Self::EntitlementDelete,
            "GUILD_CREATE" => Self::GuildCreate,
            "GUILD_UPDATE" => Self::GuildUpdate,
            "GUILD_DELETE" => Self::GuildDelete,
            "GUILD_AUDIT_LOG_ENTRY_CREATE" => Self::GuildAuditLogEntryCreate,
            "GUILD_BAN_ADD" => Self::GuildBanAdd,
            "GUILD_BAN_REMOVE" => Self::GuildBanRemove,
            "GUILD_EMOJIS_UPDATE" => Self::GuildEmojisUpdate,
            "GUILD_STICKERS_UPDATE" => Self::GuildStickersUpdate,
            "GUILD_INTEGRATIONS_UPDATE" => Self::GuildIntegrationsUpdate,
            "GUILD_MEMBER_ADD" => Self::GuildMemberAdd,
            "GUILD_MEMBER_REMOVE" => Self::GuildMemberRemove,
            "GUILD_MEMBER_UPDATE" => Self::GuildMemberUpdate,
            "GUILD_MEMBERS_CHUNK" => Self::GuildMembersChunk,
            "GUILD_ROLE_CREATE" => Self::GuildRoleCreate,
            "GUILD_ROLE_UPDATE" => Self::GuildRoleUpdate,
            "GUILD_ROLE_DELETE" => Self::GuildRoleDelete,
            "GUILD_SCHEDULED_EVENT_CREATE" => Self::GuildScheduledEventCreate,
            "GUILD_SCHEDULED_EVENT_UPDATE" => Self::GuildScheduledEventUpdate,
            "GUILD_SCHEDULED_EVENT_DELETE" => Self::GuildScheduledEventDelete,
            "GUILD_SCHEDULED_EVENT_USER_ADD" => Self::GuildScheduledEventUserAdd,
            "GUILD_SCHEDULED_EVENT_USER_REMOVE" => Self::GuildScheduledEventUserRemove,
            "GUILD_SOUNDBOARD_SOUND_CREATE" => Self::GuildSoundboardSoundCreate,
            "GUILD_SOUNDBOARD_SOUND_UPDATE" => Self::GuildSoundboardSoundUpdate,
            "GUILD_SOUNDBOARD_SOUND_DELETE" => Self::GuildSoundboardSoundDelete,
            "GUILD_SOUNDBOARD_SOUNDS_UPDATE" => Self::GuildSoundboardSoundsUpdate,
            "INTEGRATION_CREATE" => Self::IntegrationCreate,
            "INTEGRATION_UPDATE" => Self::IntegrationUpdate,
            "INTEGRATION_DELETE" => Self::IntegrationDelete,
            "INTERACTION_CREATE" => Self::InteractionCreate,
            "INVITE_CREATE" => Self::InviteCreate,
            "INVITE_DELETE" => Self::InviteDelete,
            "MESSAGE_CREATE" => Self::MessageCreate,
            "MESSAGE_UPDATE" => Self::MessageUpdate,
            "MESSAGE_DELETE" => Self::MessageDelete,
            "MESSAGE_DELETE_BULK" => Self::MessageDeleteBulk,
            "MESSAGE_REACTION_ADD" => Self::MessageReactionAdd,
            "MESSAGE_REACTION_REMOVE" => Self::MessageReactionRemove,
            "MESSAGE_REACTION_REMOVE_ALL" => Self::MessageReactionRemoveAll,
            "MESSAGE_REACTION_REMOVE_EMOJI" => Self::MessageReactionRemoveEmoji,
            "MESSAGE_POLL_VOTE_ADD" => Self::MessagePollVoteAdd,
            "MESSAGE_POLL_VOTE_REMOVE" => Self::MessagePollVoteRemove,
            "PRESENCE_UPDATE" => Self::PresenceUpdate,
            "PASSIVE_UPDATE_V1" => Self::PassiveUpdateV1,
            "STAGE_INSTANCE_CREATE" => Self::StageInstanceCreate,
            "STAGE_INSTANCE_UPDATE" => Self::StageInstanceUpdate,
            "STAGE_INSTANCE_DELETE" => Self::StageInstanceDelete,
            "SUBSCRIPTION_CREATE" => Self::SubscriptionCreate,
            "SUBSCRIPTION_UPDATE" => Self::SubscriptionUpdate,
            "SUBSCRIPTION_DELETE" => Self::SubscriptionDelete,
            "TYPING_START" => Self::TypingStart,
            "USER_UPDATE" => Self::UserUpdate,
            "VOICE_CHANNEL_EFFECT_SEND" => Self::VoiceChannelEffectSend,
            "VOICE_STATE_UPDATE" => Self::VoiceStateUpdate,
            "VOICE_SERVER_UPDATE" => Self::VoiceServerUpdate,
            "WEBHOOKS_UPDATE" => Self::WebhooksUpdate,
            "RELATIONSHIP_ADD" => Self::RelationshipAdd,
            "RELATIONSHIP_REMOVE" => Self::RelationshipRemove,
            _ => Self::Unknown(name.to_string()),
        }
    }

    pub fn as_str(&self) -> &str {
        match self {
            Self::Ready => "READY",
            Self::ReadySupplemental => "READY_SUPPLEMENTAL",
            Self::Resumed => "RESUMED",
            Self::ApplicationCommandPermissionsUpdate => "APPLICATION_COMMAND_PERMISSIONS_UPDATE",
            Self::AutoModerationRuleCreate => "AUTO_MODERATION_RULE_CREATE",
            Self::AutoModerationRuleUpdate => "AUTO_MODERATION_RULE_UPDATE",
            Self::AutoModerationRuleDelete => "AUTO_MODERATION_RULE_DELETE",
            Self::AutoModerationActionExecution => "AUTO_MODERATION_ACTION_EXECUTION",
            Self::ChannelCreate => "CHANNEL_CREATE",
            Self::ChannelUpdate => "CHANNEL_UPDATE",
            Self::ChannelDelete => "CHANNEL_DELETE",
            Self::ChannelPinsUpdate => "CHANNEL_PINS_UPDATE",
            Self::ThreadCreate => "THREAD_CREATE",
            Self::ThreadUpdate => "THREAD_UPDATE",
            Self::ThreadDelete => "THREAD_DELETE",
            Self::ThreadListSync => "THREAD_LIST_SYNC",
            Self::ThreadMemberUpdate => "THREAD_MEMBER_UPDATE",
            Self::ThreadMembersUpdate => "THREAD_MEMBERS_UPDATE",
            Self::EntitlementCreate => "ENTITLEMENT_CREATE",
            Self::EntitlementUpdate => "ENTITLEMENT_UPDATE",
            Self::EntitlementDelete => "ENTITLEMENT_DELETE",
            Self::GuildCreate => "GUILD_CREATE",
            Self::GuildUpdate => "GUILD_UPDATE",
            Self::GuildDelete => "GUILD_DELETE",
            Self::GuildAuditLogEntryCreate => "GUILD_AUDIT_LOG_ENTRY_CREATE",
            Self::GuildBanAdd => "GUILD_BAN_ADD",
            Self::GuildBanRemove => "GUILD_BAN_REMOVE",
            Self::GuildEmojisUpdate => "GUILD_EMOJIS_UPDATE",
            Self::GuildStickersUpdate => "GUILD_STICKERS_UPDATE",
            Self::GuildIntegrationsUpdate => "GUILD_INTEGRATIONS_UPDATE",
            Self::GuildMemberAdd => "GUILD_MEMBER_ADD",
            Self::GuildMemberRemove => "GUILD_MEMBER_REMOVE",
            Self::GuildMemberUpdate => "GUILD_MEMBER_UPDATE",
            Self::GuildMembersChunk => "GUILD_MEMBERS_CHUNK",
            Self::GuildRoleCreate => "GUILD_ROLE_CREATE",
            Self::GuildRoleUpdate => "GUILD_ROLE_UPDATE",
            Self::GuildRoleDelete => "GUILD_ROLE_DELETE",
            Self::GuildScheduledEventCreate => "GUILD_SCHEDULED_EVENT_CREATE",
            Self::GuildScheduledEventUpdate => "GUILD_SCHEDULED_EVENT_UPDATE",
            Self::GuildScheduledEventDelete => "GUILD_SCHEDULED_EVENT_DELETE",
            Self::GuildScheduledEventUserAdd => "GUILD_SCHEDULED_EVENT_USER_ADD",
            Self::GuildScheduledEventUserRemove => "GUILD_SCHEDULED_EVENT_USER_REMOVE",
            Self::GuildSoundboardSoundCreate => "GUILD_SOUNDBOARD_SOUND_CREATE",
            Self::GuildSoundboardSoundUpdate => "GUILD_SOUNDBOARD_SOUND_UPDATE",
            Self::GuildSoundboardSoundDelete => "GUILD_SOUNDBOARD_SOUND_DELETE",
            Self::GuildSoundboardSoundsUpdate => "GUILD_SOUNDBOARD_SOUNDS_UPDATE",
            Self::IntegrationCreate => "INTEGRATION_CREATE",
            Self::IntegrationUpdate => "INTEGRATION_UPDATE",
            Self::IntegrationDelete => "INTEGRATION_DELETE",
            Self::InteractionCreate => "INTERACTION_CREATE",
            Self::InviteCreate => "INVITE_CREATE",
            Self::InviteDelete => "INVITE_DELETE",
            Self::MessageCreate => "MESSAGE_CREATE",
            Self::MessageUpdate => "MESSAGE_UPDATE",
            Self::MessageDelete => "MESSAGE_DELETE",
            Self::MessageDeleteBulk => "MESSAGE_DELETE_BULK",
            Self::MessageReactionAdd => "MESSAGE_REACTION_ADD",
            Self::MessageReactionRemove => "MESSAGE_REACTION_REMOVE",
            Self::MessageReactionRemoveAll => "MESSAGE_REACTION_REMOVE_ALL",
            Self::MessageReactionRemoveEmoji => "MESSAGE_REACTION_REMOVE_EMOJI",
            Self::MessagePollVoteAdd => "MESSAGE_POLL_VOTE_ADD",
            Self::MessagePollVoteRemove => "MESSAGE_POLL_VOTE_REMOVE",
            Self::PresenceUpdate => "PRESENCE_UPDATE",
            Self::PassiveUpdateV1 => "PASSIVE_UPDATE_V1",
            Self::StageInstanceCreate => "STAGE_INSTANCE_CREATE",
            Self::StageInstanceUpdate => "STAGE_INSTANCE_UPDATE",
            Self::StageInstanceDelete => "STAGE_INSTANCE_DELETE",
            Self::SubscriptionCreate => "SUBSCRIPTION_CREATE",
            Self::SubscriptionUpdate => "SUBSCRIPTION_UPDATE",
            Self::SubscriptionDelete => "SUBSCRIPTION_DELETE",
            Self::TypingStart => "TYPING_START",
            Self::UserUpdate => "USER_UPDATE",
            Self::VoiceChannelEffectSend => "VOICE_CHANNEL_EFFECT_SEND",
            Self::VoiceStateUpdate => "VOICE_STATE_UPDATE",
            Self::VoiceServerUpdate => "VOICE_SERVER_UPDATE",
            Self::WebhooksUpdate => "WEBHOOKS_UPDATE",
            Self::RelationshipAdd => "RELATIONSHIP_ADD",
            Self::RelationshipRemove => "RELATIONSHIP_REMOVE",
            Self::Unknown(name) => name.as_str(),
        }
    }
}

#[derive(Debug, Clone)]
pub struct DispatchEvent {
    pub kind: DispatchEventType,
    pub sequence: Option<u64>,
    pub data: Value,
}

impl DispatchEvent {
    pub fn from_gateway_payload(event_type: &str, sequence: Option<u64>, data: Value) -> Self {
        Self {
            kind: DispatchEventType::from_event_name(event_type),
            sequence,
            data,
        }
    }

    pub fn name(&self) -> &str {
        self.kind.as_str()
    }
}
