use toml;
use crate::bootstrap::single::bootstrap_single_node;
use crate::chain::builder::ChainBuilder;
use crate::error::Error;
use crate::framework::base::HasOverrides;
use crate::framework::base::{run_basic_test, BasicTest, TestConfigOverride};
use crate::types::config::TestConfig;
use crate::types::single::node::FullNode;
pub fn run_binary_node_test<Test, Overrides>(test: &Test) -> Result<(), Error>
where
    Test: BinaryNodeTest,
    Test: HasOverrides<Overrides = Overrides>,
    Overrides: NodeConfigOverride + NodeGenesisOverride + TestConfigOverride,
{
    run_basic_test(&RunBinaryNodeTest { test })
}
pub fn run_single_node_test<Test, Overrides>(test: &Test) -> Result<(), Error>
where
    Test: BinaryNodeTest,
    Test: HasOverrides<Overrides = Overrides>,
    Overrides: NodeConfigOverride + NodeGenesisOverride + TestConfigOverride,
{
    run_basic_test(&RunSingleNodeTest { test })
}
pub trait BinaryNodeTest {
    fn run(&self, config: &TestConfig, node_a: FullNode, node_b: FullNode) -> Result<(), Error>;
}
pub trait NodeConfigOverride {
    fn modify_node_config(&self, config: &mut toml::Value) -> Result<(), Error>;
}
pub trait NodeGenesisOverride {
    fn modify_genesis_file(&self, genesis: &mut serde_json::Value) -> Result<(), Error>;
}
pub struct RunBinaryNodeTest<'a, Test> {
    pub test: &'a Test,
}
pub struct RunSingleNodeTest<'a, Test> {
    pub test: &'a Test,
}
impl<'a, Test, Overrides> BasicTest for RunBinaryNodeTest<'a, Test>
where
    Test: BinaryNodeTest,
    Test: HasOverrides<Overrides = Overrides>,
    Overrides: NodeConfigOverride + NodeGenesisOverride,
{
    fn run(&self, config: &TestConfig, builder: &ChainBuilder) -> Result<(), Error> {
        let node_a = bootstrap_single_node(
            builder,
            "1",
            config.bootstrap_with_random_ids,
            |config| self.test.get_overrides().modify_node_config(config),
            |genesis| self.test.get_overrides().modify_genesis_file(genesis),
            0,
        )?;
        let node_b = bootstrap_single_node(
            builder,
            "2",
            config.bootstrap_with_random_ids,
            |config| self.test.get_overrides().modify_node_config(config),
            |genesis| self.test.get_overrides().modify_genesis_file(genesis),
            1,
        )?;
        let _node_process_a = node_a.process.clone();
        let _node_process_b = node_b.process.clone();
        self.test.run(config, node_a, node_b)?;
        Ok(())
    }
}
impl<'a, Test, Overrides> BasicTest for RunSingleNodeTest<'a, Test>
where
    Test: BinaryNodeTest,
    Test: HasOverrides<Overrides = Overrides>,
    Overrides: NodeConfigOverride + NodeGenesisOverride,
{
    fn run(&self, config: &TestConfig, builder: &ChainBuilder) -> Result<(), Error> {
        let node = bootstrap_single_node(
            builder,
            "1",
            config.bootstrap_with_random_ids,
            |config| self.test.get_overrides().modify_node_config(config),
            |genesis| self.test.get_overrides().modify_genesis_file(genesis),
            0,
        )?;
        let _node_process = node.process.clone();
        self.test.run(config, node.clone(), node)?;
        Ok(())
    }
}
impl<'a, Test, Overrides> HasOverrides for RunBinaryNodeTest<'a, Test>
where
    Test: HasOverrides<Overrides = Overrides>,
{
    type Overrides = Overrides;
    fn get_overrides(&self) -> &Self::Overrides {
        self.test.get_overrides()
    }
}
impl<'a, Test, Overrides> HasOverrides for RunSingleNodeTest<'a, Test>
where
    Test: HasOverrides<Overrides = Overrides>,
{
    type Overrides = Overrides;
    fn get_overrides(&self) -> &Self::Overrides {
        self.test.get_overrides()
    }
}