/* These are temporarily disabled due to their non-deterministic behaviour and impending update to
 * gossipsub 1.1. We leave these here as a template for future test upgrades


#![cfg(test)]
use crate::types::GossipEncoding;
use ::types::{BeaconBlock, EthSpec, MinimalEthSpec, Signature, SignedBeaconBlock};
use lighthouse_network::*;
use slog::{debug, Level};

type E = MinimalEthSpec;

mod common;

/* Gossipsub tests */
// Note: The aim of these tests is not to test the robustness of the gossip network
// but to check if the gossipsub implementation is behaving according to the specifications.

// Test if gossipsub message are forwarded by nodes with a simple linear topology.
//
//                Topology used in test
//
// node1 <-> node2 <-> node3 ..... <-> node(n-1) <-> node(n)

#[tokio::test]
async fn test_gossipsub_forward() {
    // set up the logging. The level and enabled or not
    let log = common::build_log(Level::Info, false);

    let num_nodes = 20;
    let mut nodes = common::build_linear(log.clone(), num_nodes);
    let mut received_count = 0;
    let spec = E::default_spec();
    let empty_block = BeaconBlock::empty(&spec);
    let signed_block = SignedBeaconBlock {
        message: empty_block,
        signature: Signature::empty_signature(),
    };
    let pubsub_message = PubsubMessage::BeaconBlock(Box::new(signed_block));
    let publishing_topic: String = pubsub_message
        .topics(GossipEncoding::default(), [0, 0, 0, 0])
        .first()
        .unwrap()
        .clone()
        .into();
    let mut subscribed_count = 0;
    let fut = async move {
        for node in nodes.iter_mut() {
            loop {
                match node.next_event().await {
                    Libp2pEvent::Behaviour(b) => match b {
                        BehaviourEvent::PubsubMessage {
                            topics,
                            message,
                            source,
                            id,
                        } => {
                            assert_eq!(topics.len(), 1);
                            // Assert topic is the published topic
                            assert_eq!(
                                topics.first().unwrap(),
                                &TopicHash::from_raw(publishing_topic.clone())
                            );
                            // Assert message received is the correct one
                            assert_eq!(message, pubsub_message.clone());
                            received_count += 1;
                            // Since `propagate_message` is false, need to propagate manually
                            node.swarm.propagate_message(&source, id);
                            // Test should succeed if all nodes except the publisher receive the message
                            if received_count == num_nodes - 1 {
                                debug!(log.clone(), "Received message at {} nodes", num_nodes - 1);
                                return;
                            }
                        }
                        BehaviourEvent::PeerSubscribed(_, topic) => {
                            // Publish on beacon block topic
                            if topic == TopicHash::from_raw(publishing_topic.clone()) {
                                subscribed_count += 1;
                                // Every node except the corner nodes are connected to 2 nodes.
                                if subscribed_count == (num_nodes * 2) - 2 {
                                    node.swarm.publish(vec![pubsub_message.clone()]);
                                }
                            }
                        }
                        _ => break,
                    },
                    _ => break,
                }
            }
        }
    };

    tokio::select! {
        _ = fut => {}
        _ = tokio::time::delay_for(tokio::time::Duration::from_millis(800)) => {
            panic!("Future timed out");
        }
    }
}

// Test publishing of a message with a full mesh for the topic
// Not very useful but this is the bare minimum functionality.
#[tokio::test]
async fn test_gossipsub_full_mesh_publish() {
    // set up the logging. The level and enabled or not
    let log = common::build_log(Level::Debug, false);

    // Note: This test does not propagate gossipsub messages.
    // Having `num_nodes` > `mesh_n_high` may give inconsistent results
    // as nodes may get pruned out of the mesh before the gossipsub message
    // is published to them.
    let num_nodes = 12;
    let mut nodes = common::build_full_mesh(log, num_nodes);
    let mut publishing_node = nodes.pop().unwrap();
    let spec = E::default_spec();
    let empty_block = BeaconBlock::empty(&spec);
    let signed_block = SignedBeaconBlock {
        message: empty_block,
        signature: Signature::empty_signature(),
    };
    let pubsub_message = PubsubMessage::BeaconBlock(Box::new(signed_block));
    let publishing_topic: String = pubsub_message
        .topics(GossipEncoding::default(), [0, 0, 0, 0])
        .first()
        .unwrap()
        .clone()
        .into();
    let mut subscribed_count = 0;
    let mut received_count = 0;
    let fut = async move {
        for node in nodes.iter_mut() {
            while let Libp2pEvent::Behaviour(BehaviourEvent::PubsubMessage {
                topics,
                message,
                ..
            }) = node.next_event().await
            {
                assert_eq!(topics.len(), 1);
                // Assert topic is the published topic
                assert_eq!(
                    topics.first().unwrap(),
                    &TopicHash::from_raw(publishing_topic.clone())
                );
                // Assert message received is the correct one
                assert_eq!(message, pubsub_message.clone());
                received_count += 1;
                if received_count == num_nodes - 1 {
                    return;
                }
            }
        }
        while let Libp2pEvent::Behaviour(BehaviourEvent::PeerSubscribed(_, topic)) =
            publishing_node.next_event().await
        {
            // Publish on beacon block topic
            if topic == TopicHash::from_raw(publishing_topic.clone()) {
                subscribed_count += 1;
                if subscribed_count == num_nodes - 1 {
                    publishing_node.swarm.publish(vec![pubsub_message.clone()]);
                }
            }
        }
    };
    tokio::select! {
            _ = fut => {}
            _ = tokio::time::delay_for(tokio::time::Duration::from_millis(800)) => {
                panic!("Future timed out");
            }
    }
}
*/