// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
    anyhow::{anyhow, Context as _, Error},
    cm_rust,
    component_events::events::Event,
    component_events::{events::*, matcher::*},
    fidl_fuchsia_component_decl as fdecl, fidl_fuchsia_intl as fintl, fidl_fuchsia_sys as fsys,
    fidl_fuchsia_sys2 as fsys2, fuchsia_async as fasync,
    fuchsia_component::server::ServiceFs,
    fuchsia_component_test::new::{
        Capability, ChildOptions, DirectoryContents, LocalComponentHandles, RealmBuilder, Ref,
        Route,
    },
    futures::prelude::*,
};

const DART_RUNNERS_ENVIRONMENT_NAME: &'static str = "dart_runners_env";

const TEST_NAME: &str = env!("DART_TEST_COMPONENT_NAME");

/// Wraps the dart realm builder test component, to launch and run as a Fuchsia
/// component test.
#[fuchsia::test]
async fn fuchsia_component_test_dart_tests() -> Result<(), Error> {
    let builder = RealmBuilder::new().await?;

    configure_dart_runner_environment(&builder, DART_RUNNERS_ENVIRONMENT_NAME).await?;

    let test_url = format!("#meta/{}.cm", TEST_NAME);

    // Add dart_component_to_test to the realm.
    let dart_component_to_test = builder
        .add_child(
            TEST_NAME,
            &test_url,
            ChildOptions::new().eager().environment(DART_RUNNERS_ENVIRONMENT_NAME),
        )
        .await?;

    builder
        .add_route(
            Route::new()
                .capability(Capability::protocol::<fidl_fuchsia_logger::LogSinkMarker>())
                .capability(Capability::protocol::<fsys::EnvironmentMarker>())
                .capability(Capability::protocol::<fsys::LauncherMarker>())
                .capability(Capability::protocol::<fsys::LoaderMarker>())
                .capability(Capability::protocol::<fsys2::EventSourceMarker>())
                .capability(Capability::storage("data"))
                .from(Ref::parent())
                .to(&dart_component_to_test),
        )
        .await?;

    let _realm_instance = builder.build().await?;

    // Subscribe to stopped events for child components and then
    // wait for dart_component_to_test's `Stopped` event, and exit this test.
    let event_source = EventSource::new().unwrap();
    let mut event_stream = event_source
        .subscribe(vec![EventSubscription::new(vec![Stopped::NAME])])
        .await
        .context("failed to subscribe to EventSource")?;

    // Important! The `moniker_regex` must end with `$` to ensure the
    // `EventMatcher` does not observe stopped events of child components of
    // the Dart realm builder tests.
    let event = EventMatcher::ok()
        .moniker_regex(format!("./{}$", TEST_NAME))
        .wait::<Stopped>(&mut event_stream)
        .await
        .context(format!("failed to observe {} Stopped event", TEST_NAME))?;

    let stopped_payload = event.result().map_err(|e| anyhow!("StoppedError: {:?}", e))?;

    if let ExitStatus::Crash(status) = stopped_payload.status {
        return Err(anyhow!(
            "Test failed with exit status: {} from component event: {:?}",
            status,
            event
        ));
        // Note that just printing an `error!()` log can _sometimes_ fail the
        // test, but sadly this is not reliable (timing issue?), so we must
        // return `Err()`--which (also, sadly) spews out a long and irrelevant
        // stacktrace from the Rust test. (I know it traces back to here, but
        // I'm debugging the Dart test, not the Rust test harness.)
    }
    Ok(())
}

async fn configure_dart_runner_environment(
    builder: &RealmBuilder,
    environment_name: &str,
) -> Result<(), Error> {
    let dart_runner_name =
        if cfg!(use_dart_aot_runner) { "dart_aot_runner" } else { "dart_jit_runner" };

    let dart_runner_url =
        format!("fuchsia-pkg://fuchsia.com/{}#meta/{}.cm", dart_runner_name, dart_runner_name);

    // Add the Dart runner child component, and route directories and services
    // the runner requires.
    let dart_runner =
        builder.add_child(dart_runner_name, dart_runner_url, ChildOptions::new()).await?;

    builder
        .read_only_directory("config-data", vec![&dart_runner], DirectoryContents::new())
        .await?;

    builder
        .add_route(
            Route::new()
                .capability(Capability::protocol::<fidl_fuchsia_logger::LogSinkMarker>())
                .capability(Capability::protocol::<fidl_fuchsia_posix_socket::ProviderMarker>())
                .capability(Capability::protocol::<fidl_fuchsia_tracing_provider::RegistryMarker>())
                .from(Ref::parent())
                .to(&dart_runner),
        )
        .await?;

    let local_intl_property_provider = builder
        .add_local_child(
            "local_intl_property_provider",
            move |handles| Box::pin(local_intl_property_provider_impl(handles)),
            ChildOptions::new(),
        )
        .await?;
    builder
        .add_route(
            Route::new()
                .capability(Capability::protocol::<fintl::PropertyProviderMarker>())
                .from(&local_intl_property_provider)
                .to(&dart_runner),
        )
        .await?;

    // Add a placeholder component and routes for capabilities that are not
    // expected to be used in this test scenario.
    let placeholder = builder
        .add_local_child(
            "placeholder",
            |_: LocalComponentHandles| futures::future::pending().boxed(),
            ChildOptions::new(),
        )
        .await?;
    builder
        .add_route(
            Route::new()
                .capability(Capability::protocol::<fidl_fuchsia_feedback::CrashReporterMarker>())
                .from(&placeholder)
                .to(&dart_runner),
        )
        .await?;

    // Add the runner to the environment the child will be launched in.
    let mut realm_decl = builder.get_realm_decl().await?;
    realm_decl.environments.push(cm_rust::EnvironmentDecl {
        name: String::from(environment_name),
        extends: fdecl::EnvironmentExtends::Realm,
        resolvers: vec![],
        runners: vec![cm_rust::RunnerRegistration {
            source_name: dart_runner_name.into(),
            source: cm_rust::RegistrationSource::Child(dart_runner_name.to_string()),
            target_name: dart_runner_name.into(),
        }],
        debug_capabilities: vec![],
        stop_timeout_ms: None,
    });
    builder.replace_realm_decl(realm_decl).await?;

    Ok(())
}

async fn local_intl_property_provider_impl(handles: LocalComponentHandles) -> Result<(), Error> {
    let mut fs = ServiceFs::new();
    fs.dir("svc").add_fidl_service(move |mut stream: fintl::PropertyProviderRequestStream| {
        fasync::Task::local(async move {
            while let Some(fintl::PropertyProviderRequest::GetProfile { responder }) =
                stream.try_next().await.unwrap()
            {
                responder
                    .send(fintl::Profile {
                        time_zones: Some(vec![fintl::TimeZoneId {
                            id: "America/Los_Angeles".to_string(),
                        }]),
                        ..fintl::Profile::EMPTY
                    })
                    .expect("Error sending fuchsia::intl::PropertyProvider profile response");
            }
        })
        .detach();
    });
    fs.serve_connection(handles.outgoing_dir.into_channel()).unwrap();
    fs.collect::<()>().await;

    Ok(())
}
