use crate::Error;
use nostr_rs_types::types::{Event, Filter};

/// Trait to store/query events
pub trait Storage {
    /// Result iterators
    type Iterator<'a>: Iterator<Item = Result<Event, Error>>
    where
        Self: 'a;

    /// Stores a new event into the database. This action will also creates all
    /// the needed indexes to find this event later by reference, author, kind or tag.
    fn store(&self, event: &Event) -> Result<bool, Error>;

    /// Flags the current event as initiated locally. This useful to retrieve
    /// events using `get_local_events`.
    fn set_local_event(&self, event: &Event) -> Result<(), Error>;

    /// Returns an event by its ID
    fn get_event<T: AsRef<[u8]>>(&self, id: T) -> Result<Option<Event>, Error>;

    /// Get events from the database with a given filter
    ///
    /// The first step is to use one available index to get a list of event-IDs,
    /// then call `load_and_filter_events` that will load the events from the
    /// `Events` namespace and will filter them by the given parameters.
    fn get_by_filter(&self, query: Filter) -> Result<Self::Iterator<'_>, Error>;

    /// Return a vector of all local events
    fn get_local_events(&self, limit: Option<usize>) -> Result<Self::Iterator<'_>, Error>;

    /// Stores an event, similar to store(Event), but keeps track of this event in a
    /// local index. This is useful to keep track of the events that are created by
    /// this node, to be broadcasted to new nodes in the future
    fn store_local_event(&self, event: &Event) -> Result<bool, Error> {
        let ret = self.store(event)?;
        self.set_local_event(event)?;
        Ok(ret)
    }
}
