// Copyright 2019 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 std::collections::HashSet;
use std::sync::Arc;

use fidl_fuchsia_settings::{AccessibilityMarker, AudioMarker, DisplayMarker, PrivacyMarker};

use fidl_fuchsia_settings_policy::VolumePolicyControllerMarker;

use crate::agent::storage::storage_factory::testing::InMemoryStorageFactory;
use crate::config::default_settings::DefaultSetting;
use crate::ingress::fidl::InterfaceSpec;
use crate::tests::fakes::audio_core_service;
use crate::tests::fakes::service_registry::ServiceRegistry;
use crate::AgentConfiguration;
use crate::EnabledInterfacesConfiguration;
use crate::EnvironmentBuilder;
use crate::ServiceConfiguration;
use crate::ServiceFlags;

const ENV_NAME: &str = "settings_service_configuration_test_environment";

fn get_test_interface_specs() -> HashSet<InterfaceSpec> {
    [InterfaceSpec::Accessibility, InterfaceSpec::Privacy].into()
}

#[fuchsia_async::run_until_stalled(test)]
async fn test_no_configuration_provided() {
    let factory = InMemoryStorageFactory::new();

    let default_configuration =
        EnabledInterfacesConfiguration::with_interfaces(get_test_interface_specs());

    let flags = ServiceFlags::default();
    let configuration =
        ServiceConfiguration::from(AgentConfiguration::default(), default_configuration, flags);

    let env = EnvironmentBuilder::new(Arc::new(factory))
        .configuration(configuration)
        .spawn_and_get_nested_environment(ENV_NAME)
        .await
        .unwrap();

    // No ServiceConfiguration provided, we should be able to connect to the service and make a watch call without issue.
    let service = env.connect_to_protocol::<AccessibilityMarker>().expect("Connected to service");
    let _ = service.watch().await.expect("watch completed");

    // No ServiceConfiguration provided, audio policy should not be able to connect.
    let policy = env
        .connect_to_protocol::<VolumePolicyControllerMarker>()
        .expect("Connected to policy service");
    let _ = policy.get_properties().await.expect_err("Policy get should fail");
}

#[fuchsia_async::run_until_stalled(test)]
async fn test_default_interfaces_configuration_provided() {
    let factory = InMemoryStorageFactory::new();

    // Load test configuration, which only has Display, default will not be used.
    let configuration = DefaultSetting::new(None, "/config/data/interface_configuration.json")
        .load_default_value()
        .expect("invalid interface configuration")
        .expect("no enabled interface configuration provided");

    let flags = ServiceFlags::default();
    let configuration =
        ServiceConfiguration::from(AgentConfiguration::default(), configuration, flags);

    let env = EnvironmentBuilder::new(Arc::new(factory))
        .configuration(configuration)
        .spawn_and_get_nested_environment(ENV_NAME)
        .await
        .unwrap();

    let _ = env.connect_to_protocol::<DisplayMarker>().expect("Connected to service");

    // Any calls to the privacy service should fail since the service isn't included in the configuration.
    let privacy_service = env.connect_to_protocol::<PrivacyMarker>().unwrap();
    let _ = privacy_service.watch().await.expect_err("watch completed");
}

// Verify that providing a policy in the interface configuration allows us to connect to it.
#[fuchsia_async::run_until_stalled(test)]
async fn test_policy_configuration_provided() {
    let factory = InMemoryStorageFactory::new();

    let flags = ServiceFlags::default();
    let configuration = ServiceConfiguration::from(
        AgentConfiguration::default(),
        // Include audio setting so audio policy works.
        EnabledInterfacesConfiguration::with_interfaces(
            [InterfaceSpec::Audio, InterfaceSpec::AudioPolicy].into(),
        ),
        flags,
    );

    // Include fake audio core service so we can be sure there's no funkiness if audio setting
    // connects to the real audio core.
    let service_registry = ServiceRegistry::create();
    let audio_core_service_handle = audio_core_service::Builder::new().build();
    service_registry.lock().await.register_service(audio_core_service_handle.clone());

    let env = EnvironmentBuilder::new(Arc::new(factory))
        .service(ServiceRegistry::serve(service_registry))
        .configuration(configuration)
        .spawn_and_get_nested_environment(ENV_NAME)
        .await
        .unwrap();

    let _ = env.connect_to_protocol::<AudioMarker>().expect("Connected to service");

    // Service configuration includes volume policy and audio setting, so calls to volume policy
    // will succeed.
    let policy = env
        .connect_to_protocol::<VolumePolicyControllerMarker>()
        .expect("Connected to policy service");
    let _ = policy.get_properties().await.expect("Policy get should succeed");
}

// Verify that providing a policy in the interface configuration without its dependencies causes
// connections to fali.
#[fuchsia_async::run_until_stalled(test)]
async fn test_policy_configuration_provided_without_base_setting() {
    let factory = InMemoryStorageFactory::new();

    let flags = ServiceFlags::default();
    let configuration = ServiceConfiguration::from(
        AgentConfiguration::default(),
        // Don't include audio setting so audio policy won't work.
        EnabledInterfacesConfiguration::with_interfaces([InterfaceSpec::AudioPolicy].into()),
        flags,
    );

    let env = EnvironmentBuilder::new(Arc::new(factory))
        .configuration(configuration)
        .spawn_and_get_nested_environment(ENV_NAME)
        .await
        .unwrap();

    // Audio policy service connection should fail since its dependency on the Audio setting was not
    // satisfied.
    let policy = env
        .connect_to_protocol::<VolumePolicyControllerMarker>()
        .expect("Connected to policy service");
    let _ = policy.get_properties().await.expect_err("Policy get should fail");
}
