use std::collections::HashMap;
use std::sync::{Arc, Mutex};

#[derive(Clone, Debug)]
struct ActivePollEntry {
    project_id: String,
    label: String,
    count: usize,
}

#[derive(Clone, Default)]
pub struct ActivityState {
    active_polls: Arc<Mutex<HashMap<String, ActivePollEntry>>>,
}

impl ActivityState {
    pub fn start_poll(&self, key: &str, project_id: &str, label: &str) {
        let mut polls = self
            .active_polls
            .lock()
            .unwrap_or_else(|poison| poison.into_inner());
        let entry = polls.entry(key.to_string()).or_insert_with(|| ActivePollEntry {
            project_id: project_id.to_string(),
            label: label.to_string(),
            count: 0,
        });
        entry.project_id = project_id.to_string();
        entry.label = label.to_string();
        entry.count += 1;
    }

    pub fn finish_poll(&self, key: &str) {
        let mut polls = self
            .active_polls
            .lock()
            .unwrap_or_else(|poison| poison.into_inner());
        if let Some(entry) = polls.get_mut(key) {
            if entry.count > 1 {
                entry.count -= 1;
            } else {
                polls.remove(key);
            }
        }
    }

    pub fn list_project_polls(&self, project_id: &str) -> Vec<(String, String)> {
        let polls = self
            .active_polls
            .lock()
            .unwrap_or_else(|poison| poison.into_inner());

        polls
            .iter()
            .filter(|(_, entry)| entry.project_id == project_id)
            .map(|(key, entry)| (key.clone(), entry.label.clone()))
            .collect()
    }
}

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

    #[test]
    fn test_activity_state_tracks_concurrent_polls() {
        let state = ActivityState::default();

        state.start_poll("tuleap:tracker-1", "project-1", "Tracker A");
        state.start_poll("tuleap:tracker-1", "project-1", "Tracker A");
        assert_eq!(state.list_project_polls("project-1").len(), 1);

        state.finish_poll("tuleap:tracker-1");
        assert_eq!(state.list_project_polls("project-1").len(), 1);

        state.finish_poll("tuleap:tracker-1");
        assert_eq!(state.list_project_polls("project-1").len(), 0);
    }
}
