use libremetaverse::http::{DownloadManager, DownloadRequest};
use libremetaverse::{
    CapsRateLimiter, ConnectionSettings, GridClient, HttpCapsClientProgressReport,
    IBakingTextureProvider, LoginCredential, LoginProgressEventArgs, NetworkManager,
    NetworkManagerDisconnectType, Settings, TexturePipeline, TexturePipelineSettings,
    UDPPacketBuffer,
};
use libremetaverse_types::compat::{CancellationToken, EventHandler, IProgress, Subscription, Uri};

fn member_id<T>(result: Result<T, libremetaverse::Error>) -> &'static str {
    result
        .err()
        .expect("failure-only shim unexpectedly returned a value")
        .csharp_member()
        .expect("failure-only shim error")
}

async fn compile_login_shutdown_flows(
    network: &NetworkManager,
    limiter: &CapsRateLimiter,
    credential: LoginCredential,
) {
    let token = CancellationToken::default();
    let _ = network
        .login_with_login_credential_string_string_cancellation_token(
            credential,
            String::new(),
            String::new(),
            Some(token.clone()),
        )
        .await;
    let _ = limiter.acquire(Uri(String::new()), Some(token)).await;
    let _ = network
        .shutdown_with_disconnect_type_string_7641243c(
            NetworkManagerDisconnectType::ClientInitiated,
            String::new(),
        )
        .await;
}

async fn compile_request_settings_flows(
    downloads: &DownloadManager,
    texture_pipeline: &TexturePipeline,
    settings: &Settings,
    request: DownloadRequest,
    progress: Box<dyn IProgress<HttpCapsClientProgressReport>>,
) {
    let token = CancellationToken::default();
    let _ = downloads
        .download_with_uri_i_progress_cancellation_token(Uri(String::new()), progress, token)
        .await;
    let _ = downloads.queue_download_with_download_request(request);
    let _ = texture_pipeline.shutdown();
    let _ = settings.connection();
}

fn compile_object_safe_texture_request(
    provider: &dyn IBakingTextureProvider,
    texture_id: libremetaverse_types::UUID,
) {
    drop(provider.request_texture(texture_id, Some(CancellationToken::default())));
}

#[test]
fn runtime_flows_have_typed_callable_signatures() {
    let _: fn(&NetworkManager, EventHandler<LoginProgressEventArgs>) -> Subscription =
        NetworkManager::subscribe_login_progress;
    let _: fn(GridClient) -> Result<Settings, libremetaverse::Error> = Settings::new;
    let _ = compile_login_shutdown_flows;
    let _ = compile_request_settings_flows;
    let _ = compile_object_safe_texture_request;
}

#[test]
fn core_constructors_fail_before_starting_runtime_work() {
    assert_eq!(
        member_id(GridClient::new()),
        "M:LibreMetaverse.GridClient.#ctor"
    );
    assert_eq!(
        member_id(ConnectionSettings::new()),
        "M:LibreMetaverse.ConnectionSettings.#ctor"
    );
    assert_eq!(
        member_id(CapsRateLimiter::new_with_constructor()),
        "M:LibreMetaverse.CapsRateLimiter.#ctor"
    );
    assert_eq!(
        member_id(TexturePipelineSettings::new()),
        "M:LibreMetaverse.TexturePipelineSettings.#ctor"
    );
    assert_eq!(
        member_id(UDPPacketBuffer::new_with_constructor()),
        "M:LibreMetaverse.UDPPacketBuffer.#ctor"
    );
}
