// Generated by Qleany v1.7.3 from frontend_flat_event.tera

//! Flat event representation for simplified consumer-side matching.
//!
//! Collapses the nested `Origin → DirectAccessEntity → EntityEvent` hierarchy
//! into a single-level `FlatEventKind` enum. Every consumer can subscribe to
//! all events once and match on a flat enum instead of reconstructing nested
//! `Origin` values.

use common::event::{
    AllEvent, DirectAccessEntity, DocumentEditingEvent, DocumentFormattingEvent,
    DocumentInspectionEvent, DocumentIoEvent, DocumentSearchEvent, EntityEvent, Event,
    LongOperationEvent, Origin, UndoRedoEvent,
};
use common::types::EntityId;

/// Flat representation of all event origins.
///
/// Collapses `Origin → DirectAccessEntity → EntityEvent` into a single level.
/// Generated from the manifest: adding an entity or feature adds variants,
/// and the compiler flags every consumer that needs updating.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum FlatEventKind {
    // Per-entity events
    RootCreated,
    RootUpdated,
    RootRemoved,
    DocumentCreated,
    DocumentUpdated,
    DocumentRemoved,
    FrameCreated,
    FrameUpdated,
    FrameRemoved,
    BlockCreated,
    BlockUpdated,
    BlockRemoved,
    ListCreated,
    ListUpdated,
    ListRemoved,
    ResourceCreated,
    ResourceUpdated,
    ResourceRemoved,
    TableCreated,
    TableUpdated,
    TableRemoved,
    TableCellCreated,
    TableCellUpdated,
    TableCellRemoved,

    // Per-feature use case events
    DocumentEditingInsertText,
    DocumentEditingDeleteText,
    DocumentEditingInsertBlock,
    DocumentEditingInsertImage,
    DocumentEditingInsertFrame,
    DocumentEditingInsertFormattedText,
    DocumentEditingCreateList,
    DocumentEditingInsertList,
    DocumentEditingAddBlockToList,
    DocumentEditingRemoveBlockFromList,
    DocumentEditingInsertFragment,
    DocumentEditingInsertHtmlAtPosition,
    DocumentEditingInsertMarkdownAtPosition,
    DocumentEditingInsertTable,
    DocumentEditingRemoveTable,
    DocumentEditingInsertTableRow,
    DocumentEditingInsertTableColumn,
    DocumentEditingRemoveTableRow,
    DocumentEditingRemoveTableColumn,
    DocumentEditingMergeTableCells,
    DocumentEditingSplitTableCell,

    DocumentFormattingSetTextFormat,
    DocumentFormattingMergeTextFormat,
    DocumentFormattingSetBlockFormat,
    DocumentFormattingSetFrameFormat,
    DocumentFormattingSetTableFormat,
    DocumentFormattingSetTableCellFormat,
    DocumentFormattingSetListFormat,

    DocumentIoImportPlainText,
    DocumentIoExportPlainText,
    DocumentIoImportMarkdown,
    DocumentIoExportMarkdown,
    DocumentIoImportHtml,
    DocumentIoExportHtml,
    DocumentIoExportLatex,
    DocumentIoExportDocx,

    DocumentSearchFindText,
    DocumentSearchFindAll,
    DocumentSearchReplaceText,

    DocumentInspectionGetDocumentStats,
    DocumentInspectionGetTextAtPosition,
    DocumentInspectionGetBlockAtPosition,
    DocumentInspectionExtractFragment,

    // Undo/redo
    UndoPerformed,
    RedoPerformed,
    CompositeBegin,
    CompositeEnd,
    CompositeCancelled,

    // Long operations
    LongOperationStarted,
    LongOperationProgress,
    LongOperationCompleted,
    LongOperationFailed,
    LongOperationCancelled,

    // System
    Reset,
}

/// An event with a flattened kind, ready for consumer-side matching.
#[derive(Debug, Clone)]
pub struct FlatEvent {
    pub kind: FlatEventKind,
    pub ids: Vec<EntityId>,
    pub data: Option<String>,
}

impl From<Event> for FlatEvent {
    fn from(event: Event) -> Self {
        let kind = match &event.origin {
            Origin::DirectAccess(da) => match da {
                DirectAccessEntity::All(AllEvent::Reset) => FlatEventKind::Reset,

                DirectAccessEntity::Root(EntityEvent::Created) => FlatEventKind::RootCreated,
                DirectAccessEntity::Root(EntityEvent::Updated) => FlatEventKind::RootUpdated,
                DirectAccessEntity::Root(EntityEvent::Removed) => FlatEventKind::RootRemoved,
                DirectAccessEntity::Document(EntityEvent::Created) => {
                    FlatEventKind::DocumentCreated
                }
                DirectAccessEntity::Document(EntityEvent::Updated) => {
                    FlatEventKind::DocumentUpdated
                }
                DirectAccessEntity::Document(EntityEvent::Removed) => {
                    FlatEventKind::DocumentRemoved
                }
                DirectAccessEntity::Frame(EntityEvent::Created) => FlatEventKind::FrameCreated,
                DirectAccessEntity::Frame(EntityEvent::Updated) => FlatEventKind::FrameUpdated,
                DirectAccessEntity::Frame(EntityEvent::Removed) => FlatEventKind::FrameRemoved,
                DirectAccessEntity::Block(EntityEvent::Created) => FlatEventKind::BlockCreated,
                DirectAccessEntity::Block(EntityEvent::Updated) => FlatEventKind::BlockUpdated,
                DirectAccessEntity::Block(EntityEvent::Removed) => FlatEventKind::BlockRemoved,
                DirectAccessEntity::List(EntityEvent::Created) => FlatEventKind::ListCreated,
                DirectAccessEntity::List(EntityEvent::Updated) => FlatEventKind::ListUpdated,
                DirectAccessEntity::List(EntityEvent::Removed) => FlatEventKind::ListRemoved,
                DirectAccessEntity::Resource(EntityEvent::Created) => {
                    FlatEventKind::ResourceCreated
                }
                DirectAccessEntity::Resource(EntityEvent::Updated) => {
                    FlatEventKind::ResourceUpdated
                }
                DirectAccessEntity::Resource(EntityEvent::Removed) => {
                    FlatEventKind::ResourceRemoved
                }
                DirectAccessEntity::Table(EntityEvent::Created) => FlatEventKind::TableCreated,
                DirectAccessEntity::Table(EntityEvent::Updated) => FlatEventKind::TableUpdated,
                DirectAccessEntity::Table(EntityEvent::Removed) => FlatEventKind::TableRemoved,
                DirectAccessEntity::TableCell(EntityEvent::Created) => {
                    FlatEventKind::TableCellCreated
                }
                DirectAccessEntity::TableCell(EntityEvent::Updated) => {
                    FlatEventKind::TableCellUpdated
                }
                DirectAccessEntity::TableCell(EntityEvent::Removed) => {
                    FlatEventKind::TableCellRemoved
                }
            },

            Origin::DocumentEditing(fe) => match fe {
                DocumentEditingEvent::InsertText => FlatEventKind::DocumentEditingInsertText,
                DocumentEditingEvent::DeleteText => FlatEventKind::DocumentEditingDeleteText,
                DocumentEditingEvent::InsertBlock => FlatEventKind::DocumentEditingInsertBlock,
                DocumentEditingEvent::InsertImage => FlatEventKind::DocumentEditingInsertImage,
                DocumentEditingEvent::InsertFrame => FlatEventKind::DocumentEditingInsertFrame,
                DocumentEditingEvent::InsertFormattedText => {
                    FlatEventKind::DocumentEditingInsertFormattedText
                }
                DocumentEditingEvent::CreateList => FlatEventKind::DocumentEditingCreateList,
                DocumentEditingEvent::InsertList => FlatEventKind::DocumentEditingInsertList,
                DocumentEditingEvent::AddBlockToList => {
                    FlatEventKind::DocumentEditingAddBlockToList
                }
                DocumentEditingEvent::RemoveBlockFromList => {
                    FlatEventKind::DocumentEditingRemoveBlockFromList
                }
                DocumentEditingEvent::InsertFragment => {
                    FlatEventKind::DocumentEditingInsertFragment
                }
                DocumentEditingEvent::InsertHtmlAtPosition => {
                    FlatEventKind::DocumentEditingInsertHtmlAtPosition
                }
                DocumentEditingEvent::InsertMarkdownAtPosition => {
                    FlatEventKind::DocumentEditingInsertMarkdownAtPosition
                }
                DocumentEditingEvent::InsertTable => FlatEventKind::DocumentEditingInsertTable,
                DocumentEditingEvent::RemoveTable => FlatEventKind::DocumentEditingRemoveTable,
                DocumentEditingEvent::InsertTableRow => {
                    FlatEventKind::DocumentEditingInsertTableRow
                }
                DocumentEditingEvent::InsertTableColumn => {
                    FlatEventKind::DocumentEditingInsertTableColumn
                }
                DocumentEditingEvent::RemoveTableRow => {
                    FlatEventKind::DocumentEditingRemoveTableRow
                }
                DocumentEditingEvent::RemoveTableColumn => {
                    FlatEventKind::DocumentEditingRemoveTableColumn
                }
                DocumentEditingEvent::MergeTableCells => {
                    FlatEventKind::DocumentEditingMergeTableCells
                }
                DocumentEditingEvent::SplitTableCell => {
                    FlatEventKind::DocumentEditingSplitTableCell
                }
            },
            Origin::DocumentFormatting(fe) => match fe {
                DocumentFormattingEvent::SetTextFormat => {
                    FlatEventKind::DocumentFormattingSetTextFormat
                }
                DocumentFormattingEvent::MergeTextFormat => {
                    FlatEventKind::DocumentFormattingMergeTextFormat
                }
                DocumentFormattingEvent::SetBlockFormat => {
                    FlatEventKind::DocumentFormattingSetBlockFormat
                }
                DocumentFormattingEvent::SetFrameFormat => {
                    FlatEventKind::DocumentFormattingSetFrameFormat
                }
                DocumentFormattingEvent::SetTableFormat => {
                    FlatEventKind::DocumentFormattingSetTableFormat
                }
                DocumentFormattingEvent::SetTableCellFormat => {
                    FlatEventKind::DocumentFormattingSetTableCellFormat
                }
                DocumentFormattingEvent::SetListFormat => {
                    FlatEventKind::DocumentFormattingSetListFormat
                }
            },
            Origin::DocumentIo(fe) => match fe {
                DocumentIoEvent::ImportPlainText => FlatEventKind::DocumentIoImportPlainText,
                DocumentIoEvent::ExportPlainText => FlatEventKind::DocumentIoExportPlainText,
                DocumentIoEvent::ImportMarkdown => FlatEventKind::DocumentIoImportMarkdown,
                DocumentIoEvent::ExportMarkdown => FlatEventKind::DocumentIoExportMarkdown,
                DocumentIoEvent::ImportHtml => FlatEventKind::DocumentIoImportHtml,
                DocumentIoEvent::ExportHtml => FlatEventKind::DocumentIoExportHtml,
                DocumentIoEvent::ExportLatex => FlatEventKind::DocumentIoExportLatex,
                DocumentIoEvent::ExportDocx => FlatEventKind::DocumentIoExportDocx,
            },
            Origin::DocumentSearch(fe) => match fe {
                DocumentSearchEvent::FindText => FlatEventKind::DocumentSearchFindText,
                DocumentSearchEvent::FindAll => FlatEventKind::DocumentSearchFindAll,
                DocumentSearchEvent::ReplaceText => FlatEventKind::DocumentSearchReplaceText,
            },
            Origin::DocumentInspection(fe) => match fe {
                DocumentInspectionEvent::GetDocumentStats => {
                    FlatEventKind::DocumentInspectionGetDocumentStats
                }
                DocumentInspectionEvent::GetTextAtPosition => {
                    FlatEventKind::DocumentInspectionGetTextAtPosition
                }
                DocumentInspectionEvent::GetBlockAtPosition => {
                    FlatEventKind::DocumentInspectionGetBlockAtPosition
                }
                DocumentInspectionEvent::ExtractFragment => {
                    FlatEventKind::DocumentInspectionExtractFragment
                }
            },
            Origin::UndoRedo(ur) => match ur {
                UndoRedoEvent::Undone => FlatEventKind::UndoPerformed,
                UndoRedoEvent::Redone => FlatEventKind::RedoPerformed,
                UndoRedoEvent::BeginComposite => FlatEventKind::CompositeBegin,
                UndoRedoEvent::EndComposite => FlatEventKind::CompositeEnd,
                UndoRedoEvent::CancelComposite => FlatEventKind::CompositeCancelled,
            },
            Origin::LongOperation(lo) => match lo {
                LongOperationEvent::Started => FlatEventKind::LongOperationStarted,
                LongOperationEvent::Progress => FlatEventKind::LongOperationProgress,
                LongOperationEvent::Completed => FlatEventKind::LongOperationCompleted,
                LongOperationEvent::Failed => FlatEventKind::LongOperationFailed,
                LongOperationEvent::Cancelled => FlatEventKind::LongOperationCancelled,
            },
        };
        FlatEvent {
            kind,
            ids: event.ids,
            data: event.data,
        }
    }
}

/// Returns `true` if this event kind represents an entity mutation (created, updated, or removed).
pub fn is_mutation(kind: &FlatEventKind) -> bool {
    use FlatEventKind::*;
    matches!(
        kind,
        RootCreated
            | RootUpdated
            | RootRemoved
            | DocumentCreated
            | DocumentUpdated
            | DocumentRemoved
            | FrameCreated
            | FrameUpdated
            | FrameRemoved
            | BlockCreated
            | BlockUpdated
            | BlockRemoved
            | ListCreated
            | ListUpdated
            | ListRemoved
            | ResourceCreated
            | ResourceUpdated
            | ResourceRemoved
            | TableCreated
            | TableUpdated
            | TableRemoved
            | TableCellCreated
            | TableCellUpdated
            | TableCellRemoved
    )
}

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

    #[test]
    fn test_entity_event_converts_to_flat() {
        let event = Event {
            origin: Origin::DirectAccess(DirectAccessEntity::All(AllEvent::Reset)),
            ids: vec![],
            data: None,
        };
        let flat: FlatEvent = event.into();
        assert_eq!(flat.kind, FlatEventKind::Reset);
    }

    #[test]
    fn test_undo_redo_converts_to_flat() {
        let event = Event {
            origin: Origin::UndoRedo(UndoRedoEvent::Undone),
            ids: vec![],
            data: None,
        };
        let flat: FlatEvent = event.into();
        assert_eq!(flat.kind, FlatEventKind::UndoPerformed);
    }

    #[test]
    fn test_is_mutation() {
        assert!(is_mutation(&FlatEventKind::RootCreated));
        assert!(is_mutation(&FlatEventKind::RootUpdated));
        assert!(is_mutation(&FlatEventKind::RootRemoved));

        assert!(is_mutation(&FlatEventKind::DocumentCreated));
        assert!(is_mutation(&FlatEventKind::DocumentUpdated));
        assert!(is_mutation(&FlatEventKind::DocumentRemoved));

        assert!(is_mutation(&FlatEventKind::FrameCreated));
        assert!(is_mutation(&FlatEventKind::FrameUpdated));
        assert!(is_mutation(&FlatEventKind::FrameRemoved));

        assert!(is_mutation(&FlatEventKind::BlockCreated));
        assert!(is_mutation(&FlatEventKind::BlockUpdated));
        assert!(is_mutation(&FlatEventKind::BlockRemoved));

        assert!(is_mutation(&FlatEventKind::ListCreated));
        assert!(is_mutation(&FlatEventKind::ListUpdated));
        assert!(is_mutation(&FlatEventKind::ListRemoved));

        assert!(is_mutation(&FlatEventKind::ResourceCreated));
        assert!(is_mutation(&FlatEventKind::ResourceUpdated));
        assert!(is_mutation(&FlatEventKind::ResourceRemoved));

        assert!(is_mutation(&FlatEventKind::TableCreated));
        assert!(is_mutation(&FlatEventKind::TableUpdated));
        assert!(is_mutation(&FlatEventKind::TableRemoved));

        assert!(is_mutation(&FlatEventKind::TableCellCreated));
        assert!(is_mutation(&FlatEventKind::TableCellUpdated));
        assert!(is_mutation(&FlatEventKind::TableCellRemoved));

        assert!(!is_mutation(&FlatEventKind::Reset));
        assert!(!is_mutation(&FlatEventKind::UndoPerformed));
        assert!(!is_mutation(&FlatEventKind::LongOperationStarted));
    }
}
