use core::convert::TryInto;
use core::time::Duration;
use ibc_relayer::chain::handle::ChainHandle;
use ibc_relayer_types::core::ics04_channel::channel::Ordering;
use ibc_relayer_types::core::ics24_host::identifier::PortId;
use crate::bootstrap::binary::channel::{
bootstrap_channel_with_connection, BootstrapChannelOptions,
};
use crate::bootstrap::nary::connection::bootstrap_connections_dynamic;
use crate::error::{handle_generic_error, Error};
use crate::types::binary::channel::ConnectedChannel;
use crate::types::nary::chains::{DynamicConnectedChains, NaryConnectedChains};
use crate::types::nary::channel::{ConnectedChannels, DynamicConnectedChannels};
use crate::types::nary::connection::{ConnectedConnections, DynamicConnectedConnections};
use crate::types::tagged::*;
use crate::util::array::{assert_same_dimension, into_nested_vec};
pub fn bootstrap_channels_with_connections_dynamic<Handle: ChainHandle>(
connections: DynamicConnectedConnections<Handle>,
chains: &Vec<Handle>,
ports: &Vec<Vec<PortId>>,
order: Ordering,
bootstrap_with_random_ids: bool,
) -> Result<DynamicConnectedChannels<Handle>, Error> {
let size = chains.len();
assert_same_dimension(size, connections.connections())?;
assert_same_dimension(size, ports)?;
let mut channels: Vec<Vec<ConnectedChannel<Handle, Handle>>> = Vec::new();
for (i, connections_b) in connections.connections().iter().enumerate() {
let mut channels_b: Vec<ConnectedChannel<Handle, Handle>> = Vec::new();
for (j, connection) in connections_b.iter().enumerate() {
if i <= j {
let chain_a = &chains[i];
let chain_b = &chains[j];
let port_a = &ports[i][j];
let port_b = &ports[j][i];
let bootstrap_options = BootstrapChannelOptions::default()
.order(order)
.bootstrap_with_random_ids(bootstrap_with_random_ids);
let channel = bootstrap_channel_with_connection(
chain_a,
chain_b,
connection.clone(),
&DualTagged::new(port_a),
&DualTagged::new(port_b),
bootstrap_options,
)?;
channels_b.push(channel);
} else {
let counter_channel = &channels[j][i];
let channel = counter_channel.clone().flip();
channels_b.push(channel);
}
}
channels.push(channels_b);
}
Ok(DynamicConnectedChannels::new(channels))
}
pub fn bootstrap_channels_with_connections<Handle: ChainHandle, const SIZE: usize>(
connections: ConnectedConnections<Handle, SIZE>,
chains: [Handle; SIZE],
ports: [[PortId; SIZE]; SIZE],
order: Ordering,
bootstrap_with_random_ids: bool,
) -> Result<ConnectedChannels<Handle, SIZE>, Error> {
let channels = bootstrap_channels_with_connections_dynamic(
connections.into(),
&chains.into(),
&into_nested_vec(ports),
order,
bootstrap_with_random_ids,
)?;
channels.try_into().map_err(handle_generic_error)
}
pub fn bootstrap_channels_and_connections_dynamic<Handle: ChainHandle>(
chains: &DynamicConnectedChains<Handle>,
ports: &Vec<Vec<PortId>>,
connection_delay: Duration,
order: Ordering,
bootstrap_with_random_ids: bool,
) -> Result<DynamicConnectedChannels<Handle>, Error> {
let connections = bootstrap_connections_dynamic(
chains.foreign_clients(),
connection_delay,
bootstrap_with_random_ids,
)?;
bootstrap_channels_with_connections_dynamic(
connections,
chains.chain_handles(),
ports,
order,
bootstrap_with_random_ids,
)
}
pub fn bootstrap_channels_and_connections<Handle: ChainHandle, const SIZE: usize>(
chains: &NaryConnectedChains<Handle, SIZE>,
ports: [[PortId; SIZE]; SIZE],
connection_delay: Duration,
order: Ordering,
bootstrap_with_random_ids: bool,
) -> Result<ConnectedChannels<Handle, SIZE>, Error> {
let channels = bootstrap_channels_and_connections_dynamic(
&chains.clone().into(),
&into_nested_vec(ports),
connection_delay,
order,
bootstrap_with_random_ids,
)?;
channels.try_into()
}