use super::*;

impl NetworkManager {
    // Direct bootstrap request handler (separate fallback mechanism from cheaper TXT bootstrap mechanism)
    #[instrument(level = "trace", target = "net", skip(self), ret, err)]
    pub async fn handle_boot_request(&self, flow: Flow) -> EyreResult<NetworkResult<()>> {
        let routing_table = self.routing_table();

        // Get a bunch of nodes with the various
        let bootstrap_nodes = routing_table.find_bootstrap_nodes_filtered(2);

        // Serialize out peer info
        let bootstrap_peerinfo: Vec<Arc<PeerInfo>> = bootstrap_nodes
            .iter()
            .filter_map(|nr| nr.get_peer_info(RoutingDomain::PublicInternet))
            .collect();
        let json_bytes = serialize_json(bootstrap_peerinfo).as_bytes().to_vec();

        // Reply with a chunk of signed routing table
        let net = self.net();
        match pin_future_closure!(net.send_data_to_existing_flow(flow, json_bytes)).await? {
            SendDataToExistingFlowResult::Sent(_) => {
                // Bootstrap reply was sent
                Ok(NetworkResult::value(()))
            }
            SendDataToExistingFlowResult::NotSent(_) => Ok(NetworkResult::no_connection_other(
                "bootstrap reply could not be sent",
            )),
        }
    }

    // Direct bootstrap request
    #[instrument(level = "trace", target = "net", err, skip(self))]
    pub async fn boot_request(&self, dial_info: DialInfo) -> EyreResult<Vec<Arc<PeerInfo>>> {
        let timeout_ms = self.config().with(|c| c.network.rpc.timeout_ms);
        // Send boot magic to requested peer address
        let data = BOOT_MAGIC.to_vec();

        let out_data: Vec<u8> = network_result_value_or_log!(self self
            .net()
            .send_recv_data_unbound_to_dial_info(dial_info, data, timeout_ms)
            .await? => [ format!(": dial_info={}, data.len={}", dial_info, data.len()) ]
        {
            return Ok(Vec::new());
        });

        let bootstrap_peerinfo_str =
            std::str::from_utf8(&out_data).wrap_err("bad utf8 in boot peerinfo")?;

        let bootstrap_peerinfo: Vec<PeerInfo> = match deserialize_json(bootstrap_peerinfo_str) {
            Ok(v) => v,
            Err(e) => {
                error!("{}", e);
                return Err(e).wrap_err("failed to deserialize peerinfo");
            }
        };

        Ok(bootstrap_peerinfo.into_iter().map(Arc::new).collect())
    }
}
