////////////////////
/// Working idea 
///
///
trait ScoreWithDep<T> {
    fn create_interpret(&self) -> Box<dyn Interpret<T>>;
    fn name(&self) -> String;
    fn get_dependencies(&self) -> Vec<TypeId>; // Force T to impl Installer<TypeId> or something
                                               // like that
}

struct PrometheusAlertScore;

impl <T> ScoreWithDep<T> for PrometheusAlertScore {
    fn create_interpret(&self) -> Box<dyn Interpret<T>> {
        todo!()
    }

    fn name(&self) -> String {
        todo!()
    }

    fn get_dependencies(&self) -> Vec<TypeId> {
        // We have to find a way to constrait here so at compile time we are only allowed to return
        // TypeId for types which can be installed by T 
        //
        // This means, for example that T must implement HelmCommand if the impl <T: HelmCommand> Installable<T> for
        // KubePrometheus calls for HelmCommand.
        vec![TypeId::of::<KubePrometheus>()]
    }
}

trait Installable{}

struct KubePrometheus;

impl Installable for KubePrometheus;
 

struct Maestro<T> {
    topology: T
}

impl <T>Maestro<T> {
  fn execute_store(&self, score: ScoreWithDep<T>) {
      score.get_dependencies().iter().for_each(|dep| {
          self.topology.ensure_dependency_ready(dep);
      });
  }
}

struct TopologyWithDep {
}

impl TopologyWithDep {
    fn ensure_dependency_ready(&self, type_id: TypeId) -> Result<(), String> {
        self.installer
    }
}
