/*
    Appellation: pattern <module>
    Contrib: @FL03
*/
/// A recognized pattern in feature sequences
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(
    feature = "serde",
    derive(serde_derive::Deserialize, serde_derive::Serialize)
)]
pub struct FeaturePattern<T = f32> {
    /// Unique identifier
    pub(crate) id: usize,
    /// Importance score
    pub(crate) importance: T,
    /// Number of times this pattern has been observed
    pub(crate) occurrences: usize,
    /// Sequence of feature IDs that form this pattern
    pub(crate) sequence: Vec<usize>,
}

impl<T> FeaturePattern<T> {
    /// Create a new feature pattern
    pub fn new(id: usize, importance: T, sequence: Vec<usize>) -> Self {
        Self {
            id,
            importance,
            occurrences: 1,
            sequence,
        }
    }
    gsw! {
        id: usize,
        occurrences: usize,
    }
    gsw! {
        importance: &T
    }
    /// returns an immutable reference to the sequence of feature IDs
    pub const fn sequence(&self) -> &Vec<usize> {
        &self.sequence
    }
    /// returns a mutable reference to the sequence of feature IDs
    pub fn sequence_mut(&mut self) -> &mut Vec<usize> {
        &mut self.sequence
    }

    /// decrement the number of occurrences
    pub fn decrement_occurrences(&mut self) {
        self.occurrences -= 1;
    }
    /// Increment the occurrence count
    pub fn increment_occurrences(&mut self) {
        self.occurrences += 1;
    }
    /// returns true is the sequence is empty
    pub fn is_empty(&self) -> bool {
        self.sequence.is_empty()
    }
    /// returns the length of the sequence
    pub fn sequence_len(&self) -> usize {
        self.sequence.len()
    }
}

impl<T> core::ops::Index<usize> for FeaturePattern<T> {
    type Output = usize;

    fn index(&self, index: usize) -> &Self::Output {
        &self.sequence[index]
    }
}

impl<T> core::ops::IndexMut<usize> for FeaturePattern<T> {
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        &mut self.sequence[index]
    }
}
