use libremetaverse::appearance::ICurrentOutfitPolicy;
use libremetaverse::{
    CapsHttpLimits, GridClient, HttpCapsClient, IBakingTextureProvider, IGridClient,
};
use libremetaverse_imaging::{ManagedImage, ManagedImageImageChannels};
use libremetaverse_rlv::{IRlvActionCallbacks, IRlvQueryCallbacks, RlvParser};
use libremetaverse_structured_data::OSD;
use libremetaverse_types::UUID;
use libremetaverse_types::compat::CancellationTokenSource;
use libremetaverse_voice_webrtc::IVoiceLogger;
use std::future::Future;
use std::time::Duration;

fn assert_send_sync<T: Send + Sync>() {}

fn assert_send_future<T: Future + Send>(future: T) {
    drop(future);
}

#[allow(clippy::type_complexity)]
fn assert_dyn_compatible(
    _grid: Option<&dyn IGridClient>,
    _baker: Option<&dyn IBakingTextureProvider>,
    _outfit: Option<&dyn ICurrentOutfitPolicy>,
    _actions: Option<&dyn IRlvActionCallbacks>,
    _queries: Option<&dyn IRlvQueryCallbacks>,
    _logger: Option<&dyn IVoiceLogger>,
) {
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    assert_send_sync::<GridClient>();
    assert_send_sync::<CancellationTokenSource>();
    assert_dyn_compatible(None, None, None, None, None, None);
    assert_send_sync::<Box<dyn IGridClient>>();
    assert_send_sync::<Box<dyn IBakingTextureProvider>>();
    assert_send_sync::<Box<dyn ICurrentOutfitPolicy>>();
    assert_send_sync::<Box<dyn IRlvActionCallbacks>>();
    assert_send_sync::<Box<dyn IRlvQueryCallbacks>>();
    assert_send_sync::<Box<dyn IVoiceLogger>>();

    let cancellation = CancellationTokenSource::new();
    let token = cancellation.token();
    assert_send_future(token.cancelled());
    cancellation.cancel();

    let id = UUID::new_with_u_int64(103)?;
    let value = OSD::from_integer_with_int32(103)?;
    assert_eq!(value.as_integer()?, 103);

    let image = ManagedImage::new(2, 2, ManagedImageImageChannels::COLOR)?;
    assert_eq!(image.to_interleaved(6)?.len(), 12);

    let rlv = RlvParser::parse_message("@version=42", id.guid(), "SemVer Port")?;
    assert_eq!(rlv.commands.len(), 1);

    let native_http = HttpCapsClient::with_native_transport(
        "MetaCrate-SemVer-Port/0.0.1",
        Duration::from_secs(1),
        1,
        None,
        CapsHttpLimits::default(),
    )?;
    drop(native_http);

    let client = GridClient::new()?;
    let as_interface: &dyn IGridClient = &client;
    assert_eq!(as_interface.settings(), client.settings());
    assert_send_future(client.dispose_with_method_87ebceff());
    client.dispose_with_method()?;
    Ok(())
}
