use serde::Serialize;
use serde_value::Value;

use super::{interpret::Interpret, topology::Topology};

pub trait Score<T: Topology>:
    std::fmt::Debug + Send + Sync + CloneBoxScore<T> + SerializeScore<T>
{
    fn create_interpret(&self) -> Box<dyn Interpret<T>>;
    fn name(&self) -> String;
}

pub trait SerializeScore<T: Topology> {
    fn serialize(&self) -> Value;
}

impl<'de, S, T> SerializeScore<T> for S
where
    T: Topology,
    S: Score<T> + Serialize,
{
    fn serialize(&self) -> Value {
        // TODO not sure if this is the right place to handle the error or it should bubble
        // up?
        serde_value::to_value(&self).expect("Score should serialize successfully")
    }
}

pub trait CloneBoxScore<T: Topology> {
    fn clone_box(&self) -> Box<dyn Score<T>>;
}

impl<S, T> CloneBoxScore<T> for S
where
    T: Topology,
    S: Score<T> + Clone + 'static,
{
    fn clone_box(&self) -> Box<dyn Score<T>> {
        Box::new(self.clone())
    }
}
