use crate::editor_runtime::bridge_events::HostCommandPayload;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum HostCommandKind {
    Undo,
    Redo,
    ReplaceContent,
    SetPageOptions,
    InsertInlineReference,
    InsertEmbedReference,
    RequestCurrentBlockId,
    SetEditable,
    Focus,
    Bootstrap,
}

impl HostCommandKind {
    pub(crate) fn from_event_name(event_name: &str) -> Option<Self> {
        match event_name {
            "undo" => Some(Self::Undo),
            "redo" => Some(Self::Redo),
            "replaceContent" | "replace-document" => Some(Self::ReplaceContent),
            "setPageOptions" | "set-page-options" => Some(Self::SetPageOptions),
            "insertInlineReference" => Some(Self::InsertInlineReference),
            "insertEmbedReference" => Some(Self::InsertEmbedReference),
            "requestCurrentBlockId" => Some(Self::RequestCurrentBlockId),
            "setEditable" | "set-editable" => Some(Self::SetEditable),
            "focus" => Some(Self::Focus),
            "bootstrap" => Some(Self::Bootstrap),
            _ => None,
        }
    }

    pub(crate) fn from_payload(payload: &HostCommandPayload) -> Option<Self> {
        payload.command.as_deref().and_then(Self::from_event_name)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn parses_command_aliases_and_canonical_names() {
        assert_eq!(
            HostCommandKind::from_event_name("replace-document"),
            Some(HostCommandKind::ReplaceContent)
        );
        assert_eq!(
            HostCommandKind::from_event_name("replaceContent"),
            Some(HostCommandKind::ReplaceContent)
        );
        assert_eq!(
            HostCommandKind::from_event_name("requestCurrentBlockId"),
            Some(HostCommandKind::RequestCurrentBlockId)
        );
    }

    #[test]
    fn reads_command_from_payload_field() {
        let payload = HostCommandPayload {
            command: Some("setEditable".to_string()),
            document_id: None,
            workspace_id: None,
            title: None,
            content: None,
            editable: Some(true),
            page_options: None,
            block_id: None,
            block_index: None,
            text: None,
            reference_document_id: None,
            reference_block_id: None,
            current_block_id: None,
            selection: None,
            revision: None,
            conflict_detection_key: None,
            read_only: None,
        };

        assert_eq!(
            HostCommandKind::from_payload(&payload),
            Some(HostCommandKind::SetEditable)
        );
    }
}
