//! Phase 29ai P3: CandidateSet — SSOT implementation
//!
//! SSOT: "0 candidates = Ok(None), 1 = Ok(Some), 2+ = Freeze(ambiguous)"

#![allow(dead_code)]

use super::Freeze;
use crate::mir::builder::control_flow::plan::DomainPlan;

#[derive(Debug, Clone)]
pub(in crate::mir::builder) struct PlanCandidate {
    pub plan: DomainPlan,
    pub rule: &'static str,
}

#[derive(Debug, Default)]
pub(in crate::mir::builder) struct CandidateSet {
    candidates: Vec<PlanCandidate>,
}

impl CandidateSet {
    pub(in crate::mir::builder) fn new() -> Self {
        Self {
            candidates: Vec::new(),
        }
    }

    pub(in crate::mir::builder) fn push(&mut self, candidate: PlanCandidate) {
        self.candidates.push(candidate);
    }

    pub(in crate::mir::builder) fn finalize(self) -> Result<Option<DomainPlan>, Freeze> {
        match self.candidates.len() {
            0 => Ok(None),
            1 => {
                let c = self.candidates.into_iter().next().expect("len == 1");
                Ok(Some(c.plan))
            }
            n => {
                let rules = self
                    .candidates
                    .iter()
                    .map(|c| c.rule)
                    .collect::<Vec<_>>()
                    .join(", ");
                Err(Freeze::ambiguous(format!(
                    "multiple plan candidates (count={}): {}",
                    n, rules
                )))
            }
        }
    }
}
