use crate::{ TestCounter, TestStatus };

use super::item::Item;
use super::case::Case;
use super::generic::Generic;

#[derive(Debug, Default)]
pub struct Plan {
    pub(crate) status:		TestStatus,
    pub(crate) path:		Vec<String>,
    pub(crate) generic:		Generic,
    pub(crate) elems:		Vec<Item>,
    pub(crate) counter:		TestCounter,
    pub(crate) num_planned:	Option<u32>,
    pub(crate) reason:		Option<String>,
}

impl Plan {
    pub fn new(parent: &Plan) -> Self
    {
	let mut path = Vec::with_capacity(parent.path.len() + 1);

	path.append(&mut parent.path.clone());
	path.push(parent.generic.name.clone());

	Self {
	    status:		TestStatus::Init,
	    path:		path,
	    generic:		Generic::default(),
	    elems:		Vec::new(),
	    counter:		TestCounter::default(),
	    num_planned:	None,
	    reason:		None,
	}
    }

    pub(crate) fn close(&mut self)
    {
	if let Some(v) = &self.num_planned {
	    let num_total = self.counter.get_total();
	    if num_total != *v {
		self.status.update(TestStatus::Fail);

		if self.reason.is_none() {
		    self.reason = Some(format!("mismatch of number of planned test cases ({} != {}",
					       num_total, *v));
		}
	    }
	}
    }

    pub fn append_plan(&mut self, plan: Box<Plan>)
    {
	self.elems.push(Item::Plan(plan));
    }

    pub fn append_case(&mut self, case: Box<Case>)
    {
	self.elems.push(Item::Case(case));
    }

    pub fn append_comment(&mut self, s: &str)
    {
	self.elems.push(Item::Comment(s.to_string()));
    }

    pub fn record_duration(&mut self, duration: std::time::Duration)
    {
	self.generic.record_duration(duration)
    }
}
