//! Storage abstraction: routes to the correct backend by entity kind.

use crate::schema::{EntityKind, TidalError};
use crate::storage::{InMemoryBackend, StorageEngine};

/// Wraps either in-memory backends (ephemeral mode) or a fjall storage
/// (persistent mode) behind a uniform interface.
///
/// M3 provides three backends: items, users, creators. In ephemeral mode
/// each is an independent `InMemoryBackend`; in persistent mode they share
/// a single `FjallStorage` with three keyspaces.
pub enum StorageBox {
    Memory {
        items: InMemoryBackend,
        users: InMemoryBackend,
        creators: InMemoryBackend,
    },
    Fjall(crate::storage::FjallStorage),
}

impl StorageBox {
    /// Reference to the items storage engine.
    pub(super) fn items_engine(&self) -> &dyn StorageEngine {
        match self {
            Self::Memory { items, .. } => items,
            Self::Fjall(f) => f.backend(EntityKind::Item),
        }
    }

    /// Reference to the users storage engine.
    pub(super) fn users_engine(&self) -> &dyn StorageEngine {
        match self {
            Self::Memory { users, .. } => users,
            Self::Fjall(f) => f.backend(EntityKind::User),
        }
    }

    /// Reference to the creators storage engine.
    pub(super) fn creators_engine(&self) -> &dyn StorageEngine {
        match self {
            Self::Memory { creators, .. } => creators,
            Self::Fjall(f) => f.backend(EntityKind::Creator),
        }
    }

    /// Flush all buffered writes to durable storage.
    pub(super) fn flush(&self) -> crate::Result<()> {
        match self {
            Self::Memory { .. } => Ok(()),
            Self::Fjall(f) => f.flush_all().map_err(TidalError::from),
        }
    }
}
