// 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.

// This declaration is required to support the `select!`.
#![recursion_limit = "256"]

use {
    crate::accessibility::accessibility_controller::AccessibilityController,
    crate::account::account_controller::AccountController,
    crate::agent::authority_impl::AuthorityImpl,
    crate::agent::base::{
        Authority, BlueprintHandle as AgentBlueprintHandle, InitializationContext, Lifespan,
    },
    crate::audio::audio_controller::AudioController,
    crate::config::base::ControllerFlag,
    crate::device::device_controller::DeviceController,
    crate::display::display_controller::DisplayController,
    crate::display::light_sensor_controller::LightSensorController,
    crate::do_not_disturb::do_not_disturb_controller::DoNotDisturbController,
    crate::input::input_controller::InputController,
    crate::inspect::inspect_broker::InspectBroker,
    crate::intl::intl_controller::IntlController,
    crate::light::light_controller::LightController,
    crate::night_mode::night_mode_controller::NightModeController,
    crate::power::power_controller::PowerController,
    crate::privacy::privacy_controller::PrivacyController,
    crate::registry::base::GenerateHandler,
    crate::registry::device_storage::DeviceStorageFactory,
    crate::registry::registry_impl::RegistryImpl,
    crate::registry::setting_handler::persist::Handler as DataHandler,
    crate::registry::setting_handler::Handler,
    crate::registry::setting_handler_factory_impl::SettingHandlerFactoryImpl,
    crate::service_context::GenerateService,
    crate::service_context::ServiceContext,
    crate::service_context::ServiceContextHandle,
    crate::setup::setup_controller::SetupController,
    crate::switchboard::accessibility_types::AccessibilityInfo,
    crate::switchboard::base::{
        AudioInfo, DisplayInfo, DoNotDisturbInfo, InputInfo, NightModeInfo, PrivacyInfo,
        SettingType, SetupInfo,
    },
    crate::switchboard::intl_types::IntlInfo,
    crate::switchboard::light_types::LightInfo,
    crate::switchboard::switchboard_impl::SwitchboardBuilder,
    anyhow::{format_err, Error},
    fidl_fuchsia_settings::*,
    fuchsia_async as fasync,
    fuchsia_component::server::{NestedEnvironment, ServiceFs, ServiceFsDir, ServiceObj},
    fuchsia_inspect::component,
    fuchsia_syslog::fx_log_err,
    futures::lock::Mutex,
    futures::StreamExt,
    serde::{Deserialize, Serialize},
    std::collections::{HashMap, HashSet},
    std::sync::Arc,
};

mod accessibility;
mod account;
mod audio;
mod clock;
mod device;
mod display;
mod do_not_disturb;
mod fidl_clone;
mod fidl_processor;
mod input;
mod inspect;
mod internal;
mod intl;
mod light;
mod night_mode;
mod power;
mod privacy;
mod setup;

pub mod agent;
pub mod config;
pub mod fidl_common;
pub mod message;
pub mod registry;
pub mod service_context;
pub mod switchboard;

/// A common trigger for exiting.
pub type ExitSender = futures::channel::mpsc::UnboundedSender<()>;

/// Runtime defines where the environment will exist. Service is meant for
/// production environments and will hydrate components to be discoverable as
/// an environment service. Nested creates a service only usable in the scope
/// of a test.
enum Runtime {
    Service,
    Nested(&'static str),
}

#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct ServiceConfiguration {
    pub services: HashSet<SettingType>,
    #[serde(default)]
    pub controller_flags: HashSet<ControllerFlag>,
}

impl ServiceConfiguration {
    pub fn with_services(services: HashSet<SettingType>) -> Self {
        Self { services, controller_flags: HashSet::new() }
    }
}

/// Environment is handed back when an environment is spawned from the
/// EnvironmentBuilder. A nested environment (if available) is returned,
/// along with a receiver to be notified when initialization/setup is
/// complete.
pub struct Environment {
    pub nested_environment: Option<NestedEnvironment>,
}

impl Environment {
    pub fn new(nested_environment: Option<NestedEnvironment>) -> Environment {
        Environment { nested_environment: nested_environment }
    }
}

/// The EnvironmentBuilder aggregates the parameters surrounding an environment
/// and ultimately spawns an environment based on them.
pub struct EnvironmentBuilder<T: DeviceStorageFactory + Send + Sync + 'static> {
    configuration: Option<ServiceConfiguration>,
    agent_blueprints: Vec<AgentBlueprintHandle>,
    event_subscriber_blueprints: Vec<internal::event::subscriber::BlueprintHandle>,
    storage_factory: Arc<Mutex<T>>,
    generate_service: Option<GenerateService>,
    handlers: HashMap<SettingType, GenerateHandler<T>>,
}

macro_rules! register_handler {
    ($handler_factory:ident, $setting_type:expr, $spawn_method:expr) => {
        $handler_factory.register($setting_type, Box::new($spawn_method));
    };
}

/// This macro conditionally adds a FIDL service handler based on the presence
/// of `SettingType`s in the available components. The caller specifies the
/// mod containing a generated fidl_io mod to handle the incoming request
/// streams, the target FIDL interface, and a list of `SettingType`s whose
/// presence will cause this handler to be included.
macro_rules! register_fidl_handler {
    ($components:ident, $service_dir:ident, $messenger_factory:ident,
            $interface:ident, $handler_mod:ident$(, $target:ident)+) => {
        if false $(|| $components.contains(&SettingType::$target))+
        {
            let factory = $messenger_factory.clone();
            $service_dir.add_fidl_service(move |stream: paste::item!{[<$interface RequestStream>]}| {
                crate::$handler_mod::fidl_io::spawn(factory.clone(), stream);
            });
        }
    }
}

impl<T: DeviceStorageFactory + Send + Sync + 'static> EnvironmentBuilder<T> {
    pub fn new(storage_factory: Arc<Mutex<T>>) -> EnvironmentBuilder<T> {
        EnvironmentBuilder {
            configuration: None,
            agent_blueprints: vec![],
            event_subscriber_blueprints: vec![],
            storage_factory: storage_factory,
            generate_service: None,
            handlers: HashMap::new(),
        }
    }

    pub fn handler(
        mut self,
        setting_type: SettingType,
        generate_handler: GenerateHandler<T>,
    ) -> EnvironmentBuilder<T> {
        self.handlers.insert(setting_type, generate_handler);
        self
    }

    /// A service generator to be used as an overlay on the ServiceContext.
    pub fn service(mut self, generate_service: GenerateService) -> EnvironmentBuilder<T> {
        self.generate_service = Some(generate_service);
        self
    }

    /// A preset configuration to load preset parameters as a base.
    pub fn configuration(mut self, configuration: ServiceConfiguration) -> EnvironmentBuilder<T> {
        self.configuration = Some(configuration);
        self
    }

    /// Setting types to participate.
    pub fn settings(mut self, settings: &[SettingType]) -> EnvironmentBuilder<T> {
        let controller_flags =
            self.configuration.take().map(|c| c.controller_flags).unwrap_or_else(|| HashSet::new());
        self.configuration(ServiceConfiguration {
            services: settings.to_vec().into_iter().collect(),
            controller_flags,
        })
    }

    /// Setting types to participate with customized controllers.
    pub fn flags(mut self, controller_flags: &[ControllerFlag]) -> EnvironmentBuilder<T> {
        let services =
            self.configuration.take().map(|c| c.services).unwrap_or_else(|| HashSet::new());
        self.configuration(ServiceConfiguration {
            services,
            controller_flags: controller_flags.iter().map(|f| *f).collect(),
        })
    }

    pub fn agents(mut self, blueprints: &[AgentBlueprintHandle]) -> EnvironmentBuilder<T> {
        self.agent_blueprints.append(&mut blueprints.to_vec());
        self
    }

    /// Event subscribers to participate
    pub fn event_subscribers(
        mut self,
        subscribers: &[internal::event::subscriber::BlueprintHandle],
    ) -> EnvironmentBuilder<T> {
        self.event_subscriber_blueprints.append(&mut subscribers.to_vec());
        self
    }

    async fn prepare_env(
        self,
        runtime: Runtime,
    ) -> Result<ServiceFs<ServiceObj<'static, ()>>, Error> {
        let mut fs = ServiceFs::new();
        // Initialize inspect.
        component::inspector().serve(&mut fs).ok();
        let service_dir =
            if let Runtime::Service = runtime { fs.dir("svc") } else { fs.root_dir() };

        let (settings, flags) = match self.configuration {
            Some(configuration) => (configuration.services, configuration.controller_flags),
            _ => (HashSet::new(), HashSet::new()),
        };

        let service_context = ServiceContext::create(self.generate_service);

        let mut handler_factory = SettingHandlerFactoryImpl::new(
            settings.clone(),
            service_context.clone(),
            self.storage_factory.clone(),
        );

        EnvironmentBuilder::get_configuration_handlers(&flags, &mut handler_factory);

        // Override the configuration handlers with any custom handlers specified
        // in the environment.
        for (setting_type, handler) in self.handlers {
            handler_factory.register(setting_type, handler);
        }

        if create_environment(
            service_dir,
            settings,
            self.agent_blueprints,
            self.event_subscriber_blueprints,
            service_context,
            Arc::new(Mutex::new(handler_factory)),
        )
        .await
        .is_err()
        {
            return Err(format_err!("could not create environment"));
        }

        Ok(fs)
    }

    pub fn spawn(self, mut executor: fasync::Executor) -> Result<(), Error> {
        match executor.run_singlethreaded(self.prepare_env(Runtime::Service)) {
            Ok(mut fs) => {
                fs.take_and_serve_directory_handle().expect("could not service directory handle");
                let () = executor.run_singlethreaded(fs.collect());

                Ok(())
            }
            Err(error) => Err(error),
        }
    }

    pub async fn spawn_nested(self, env_name: &'static str) -> Result<Environment, Error> {
        match self.prepare_env(Runtime::Nested(env_name)).await {
            Ok(mut fs) => {
                let nested_environment = Some(fs.create_salted_nested_environment(&env_name)?);
                fasync::spawn(fs.collect());

                Ok(Environment::new(nested_environment))
            }
            Err(error) => Err(error),
        }
    }

    /// Spawns a nested environment and returns the associated
    /// NestedEnvironment. Note that this is a helper function that provides a
    /// shortcut for calling EnvironmentBuilder::name() and
    /// EnvironmentBuilder::spawn().
    pub async fn spawn_and_get_nested_environment(
        self,
        env_name: &'static str,
    ) -> Result<NestedEnvironment, Error> {
        let environment = self.spawn_nested(env_name).await?;

        if let Some(env) = environment.nested_environment {
            return Ok(env);
        }

        return Err(format_err!("nested environment not created"));
    }

    fn get_configuration_handlers(
        _controller_flags: &HashSet<ControllerFlag>,
        factory_handle: &mut SettingHandlerFactoryImpl<T>,
    ) {
        // Power
        register_handler!(factory_handle, SettingType::Power, Handler::<PowerController>::spawn);
        // Accessibility
        register_handler!(
            factory_handle,
            SettingType::Accessibility,
            DataHandler::<AccessibilityInfo, AccessibilityController>::spawn
        );
        // Account
        register_handler!(
            factory_handle,
            SettingType::Account,
            Handler::<AccountController>::spawn
        );
        // Audio
        register_handler!(
            factory_handle,
            SettingType::Audio,
            DataHandler::<AudioInfo, AudioController>::spawn
        );
        // Device
        register_handler!(factory_handle, SettingType::Device, Handler::<DeviceController>::spawn);
        // Display
        register_handler!(
            factory_handle,
            SettingType::Display,
            DataHandler::<DisplayInfo, DisplayController>::spawn
        );
        // Light
        register_handler!(
            factory_handle,
            SettingType::Light,
            DataHandler::<LightInfo, LightController>::spawn
        );
        // Light sensor
        register_handler!(
            factory_handle,
            SettingType::LightSensor,
            Handler::<LightSensorController>::spawn
        );
        // Input
        register_handler!(
            factory_handle,
            SettingType::Input,
            DataHandler::<InputInfo, InputController>::spawn
        );
        // Intl
        register_handler!(
            factory_handle,
            SettingType::Intl,
            DataHandler::<IntlInfo, IntlController>::spawn
        );
        // Do not disturb
        register_handler!(
            factory_handle,
            SettingType::DoNotDisturb,
            DataHandler::<DoNotDisturbInfo, DoNotDisturbController>::spawn
        );
        // Night mode
        register_handler!(
            factory_handle,
            SettingType::NightMode,
            DataHandler::<NightModeInfo, NightModeController>::spawn
        );
        // Privacy
        register_handler!(
            factory_handle,
            SettingType::Privacy,
            DataHandler::<PrivacyInfo, PrivacyController>::spawn
        );
        // Setup
        register_handler!(
            factory_handle,
            SettingType::Setup,
            DataHandler::<SetupInfo, SetupController>::spawn
        );
    }
}

/// Brings up the settings service environment.
///
/// This method generates the necessary infrastructure to support the settings
/// service (switchboard, registry, etc.) and brings up the components necessary
/// to support the components specified in the components HashSet.
async fn create_environment<'a, T: DeviceStorageFactory + Send + Sync + 'static>(
    mut service_dir: ServiceFsDir<'_, ServiceObj<'a, ()>>,
    components: HashSet<SettingType>,
    agent_blueprints: Vec<AgentBlueprintHandle>,
    event_subscriber_blueprints: Vec<internal::event::subscriber::BlueprintHandle>,
    service_context_handle: ServiceContextHandle,
    handler_factory: Arc<Mutex<SettingHandlerFactoryImpl<T>>>,
) -> Result<(), Error> {
    let registry_messenger_factory = internal::core::message::create_hub();
    let switchboard_messenger_factory = internal::switchboard::message::create_hub();
    let setting_handler_messenger_factory = internal::handler::message::create_hub();
    let event_messenger_factory = internal::event::message::create_hub();

    for blueprint in event_subscriber_blueprints {
        blueprint.create(event_messenger_factory.clone()).await;
    }

    // Attach inspect broker, which watches messages between registry and setting handlers to
    // record settings values to inspect.
    let inspect_broker_node = component::inspector().root().create_child("setting_values");
    InspectBroker::create(setting_handler_messenger_factory.clone(), inspect_broker_node)
        .await
        .expect("could not create inspect");

    // Creates switchboard, handed to interface implementations to send messages
    // to handlers.
    SwitchboardBuilder::create()
        .registry_messenger_factory(registry_messenger_factory.clone())
        .switchboard_messenger_factory(switchboard_messenger_factory.clone())
        .build()
        .await
        .expect("could not create switchboard");

    let mut agent_authority = AuthorityImpl::create(
        internal::agent::message::create_hub(),
        switchboard_messenger_factory.clone(),
        event_messenger_factory.clone(),
    )
    .await?;

    // Creates registry, used to register handlers for setting types.
    let _ = RegistryImpl::create(
        handler_factory.clone(),
        registry_messenger_factory.clone(),
        setting_handler_messenger_factory,
    )
    .await
    .expect("could not create registry");

    register_fidl_handler!(
        components,
        service_dir,
        switchboard_messenger_factory,
        Light,
        light,
        Light
    );

    register_fidl_handler!(
        components,
        service_dir,
        switchboard_messenger_factory,
        Accessibility,
        accessibility,
        Accessibility
    );

    register_fidl_handler!(
        components,
        service_dir,
        switchboard_messenger_factory,
        Audio,
        audio,
        Audio
    );

    register_fidl_handler!(
        components,
        service_dir,
        switchboard_messenger_factory,
        Device,
        device,
        Device
    );

    register_fidl_handler!(
        components,
        service_dir,
        switchboard_messenger_factory,
        Display,
        display,
        Display,
        LightSensor
    );

    register_fidl_handler!(
        components,
        service_dir,
        switchboard_messenger_factory,
        DoNotDisturb,
        do_not_disturb,
        DoNotDisturb
    );

    register_fidl_handler!(
        components,
        service_dir,
        switchboard_messenger_factory,
        Intl,
        intl,
        Intl
    );

    register_fidl_handler!(
        components,
        service_dir,
        switchboard_messenger_factory,
        NightMode,
        night_mode,
        NightMode
    );

    register_fidl_handler!(
        components,
        service_dir,
        switchboard_messenger_factory,
        Privacy,
        privacy,
        Privacy
    );

    register_fidl_handler!(
        components,
        service_dir,
        switchboard_messenger_factory,
        Input,
        input,
        Input
    );

    register_fidl_handler!(
        components,
        service_dir,
        switchboard_messenger_factory,
        Setup,
        setup,
        Setup
    );

    for blueprint in agent_blueprints {
        if agent_authority.register(blueprint).await.is_err() {
            fx_log_err!("failed to register agent via blueprint");
        }
    }

    // Execute initialization agents sequentially
    if agent_authority
        .execute_lifespan(
            Lifespan::Initialization(InitializationContext { available_components: components }),
            service_context_handle.clone(),
            true,
        )
        .await
        .is_err()
    {
        return Err(format_err!("Agent initialization failed"));
    }

    // Execute service agents concurrently
    agent_authority
        .execute_lifespan(Lifespan::Service, service_context_handle.clone(), false)
        .await
        .ok();

    return Ok(());
}

#[cfg(test)]
mod tests;
