Documentation
use std::sync::Arc;
use tokio::sync::Mutex;

#[derive(Default, Clone)]
pub struct AudioStream {
    id: String,
    sum: i32,
    total: i32,
}
#[derive(Default, Clone)]
pub struct AudioObserver {
    streams: Arc<Mutex<Vec<AudioStream>>>,
    expected: i32,
    threshold: u8,
    previous: Vec<String>,
}

impl AudioObserver {
    pub fn new(threshold_parameter: u8, interval_parameter: i32, filter_parameter: i32) -> Self {
        let mut threshold: u8 = threshold_parameter;
        if threshold > 127 {
            threshold = 127;
        }
        let mut filter: i32 = filter_parameter;
        if filter < 0 {
            filter = 0;
        }
        if filter > 100 {
            filter = 100;
        }
        Self {
            threshold,
            expected: interval_parameter * filter / 2000,
            ..Default::default()
        }
    }

    pub async fn add_stream(&mut self, stream_id: String) {
        self.streams.lock().await.push(AudioStream {
            id: stream_id,
            ..Default::default()
        })
    }

    pub async fn remove_stream(&mut self, stream_id: String) {
        let mut streams = self.streams.lock().await;
        let mut idx = 0_usize;
        while idx < streams.len() {
            if streams[idx].id == stream_id {
                streams.remove(idx);
                continue;
            }
            idx += 1;
        }
    }

    pub async fn observe(&mut self, stream_id: String, d_bov: u8) {
        let mut streams = self.streams.lock().await;

        for stream in streams.iter_mut() {
            if stream.id == stream_id {
                if d_bov <= self.threshold {
                    stream.sum += d_bov as i32;
                    stream.total += 1;
                }
                return;
            }
        }
    }

    pub async fn calc(&mut self) -> Option<Vec<String>> {
        let mut streams = self.streams.lock().await;

        streams.sort_by(|a, b| {
            if b.total != a.total {
                return b.total.cmp(&a.total);
            }
            b.sum.cmp(&a.sum)
        });

        let mut stream_ids = Vec::new();

        for stream in streams.iter_mut() {
            if stream.total >= self.expected {
                stream_ids.push(stream.id.clone());
            }

            stream.total = 0;
            stream.sum = 0;
        }

        if self.previous.len() == stream_ids.len() {
            for idx in 0..self.previous.len() {
                if self.previous[idx] != stream_ids[idx] {
                    self.previous = stream_ids.clone();

                    return Some(stream_ids);
                }
            }
            return None;
        }
        self.previous = stream_ids.clone();

        Some(stream_ids)
    }
}