use std::sync::Arc;

use pyo3::exceptions::PyTypeError;
use pyo3::prelude::*;

use crate::extensions::tags::parametrize::Parametrization;
use crate::extensions::tags::{Tag, Tags};

#[derive(Debug, Clone)]
#[pyclass(from_py_object)]
pub struct Param {
    /// The values of the arguments
    pub(crate) values: Vec<Arc<Py<PyAny>>>,

    /// Tags associated with this parametrization
    pub(crate) tags: Tags,
}

impl Param {
    pub(crate) fn new(py: Python, values: Vec<Py<PyAny>>, tags: Vec<Py<PyAny>>) -> PyResult<Self> {
        let mut new_tags = Vec::new();

        for tag in tags {
            new_tags.push(
                Tag::try_from_py_any(py, &tag)
                    .ok_or_else(|| PyTypeError::new_err("Invalid tag"))?,
            );
        }

        Ok(Self {
            values: values.into_iter().map(Arc::new).collect(),
            tags: Tags::new(new_tags),
        })
    }

    pub(crate) fn from_parametrization(Parametrization { values, tags }: Parametrization) -> Self {
        Self { values, tags }
    }
}
