use serde::Serialize;

use crate::{
    interpret::Interpret,
    inventory::Inventory,
    modules::dhcp::DhcpScore,
    score::Score,
    topology::{DhcpServer, HAClusterTopology, HostBinding, Topology},
};

#[derive(Debug, Clone, Serialize)]
pub struct OKDDhcpScore {
    dhcp_score: DhcpScore,
}

impl OKDDhcpScore {
    pub fn new(topology: &HAClusterTopology, inventory: &Inventory) -> Self {
        let mut host_binding: Vec<HostBinding> = topology
            .control_plane
            .iter()
            .enumerate()
            .map(|(index, topology_entry)| HostBinding {
                logical_host: topology_entry.clone(),
                physical_host: inventory
                    .control_plane_host
                    .get(index)
                    .expect("Iventory should contain at least as many physical hosts as topology")
                    .clone(),
            })
            .collect();

        topology
            .workers
            .iter()
            .enumerate()
            .for_each(|(index, topology_entry)| {
                host_binding.push(HostBinding {
                    logical_host: topology_entry.clone(),
                    physical_host: inventory
                        .worker_host
                        .get(index)
                        .expect("There should be enough worker hosts to fill topology")
                        .clone(),
                })
            });

        Self {
            // TODO : we should add a tftp server to the topology instead of relying on the
            // router address, this is leaking implementation details
            dhcp_score: DhcpScore {
                host_binding,
                next_server: Some(topology.router.get_gateway()),
                boot_filename: None,
                filename: Some("undionly.kpxe".to_string()),
                filename64: Some("ipxe.efi".to_string()),
                filenameipxe: Some(format!(
                    "http://{}:8080/boot.ipxe",
                    topology.router.get_gateway()
                )),
            },
        }
    }
}

impl<T: Topology + DhcpServer> Score<T> for OKDDhcpScore {
    fn create_interpret(&self) -> Box<dyn Interpret<T>> {
        self.dhcp_score.create_interpret()
    }

    fn name(&self) -> String {
        "OKDDhcpScore".to_string()
    }
}
