// Copyright 2021 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::{Context as _, Error};
use fuchsia_component::client::connect_to_protocol_sync;
use fuchsia_component::server::ServiceFs;
use futures::StreamExt;
use kernel_manager::kernels::Kernels;
use kernel_manager::proxy::run_proxy_thread;
use kernel_manager::serve_starnix_manager;
use kernel_manager::suspend::SuspendContext;
use log::{error, info, warn};
use std::sync::Arc;
use {
    fidl_fuchsia_component_runner as frunner, fidl_fuchsia_settings as fsettings,
    fidl_fuchsia_starnix_runner as fstarnixrunner, zx,
};

enum Services {
    ComponentRunner(frunner::ComponentRunnerRequestStream),
    StarnixManager(fstarnixrunner::ManagerRequestStream),
}

const MEMORY_ROLE_NAME: &str = "fuchsia.starnix.runner";

#[fuchsia::main(logging_tags = ["starnix_runner"])]
async fn main() -> Result<(), Error> {
    if let Err(e) = fuchsia_scheduler::set_role_for_root_vmar(MEMORY_ROLE_NAME) {
        warn!(e:%; "failed to set memory role");
    }
    fuchsia_trace_provider::trace_provider_create_with_fdio();
    let config = starnix_runner_config::Config::take_from_startup_handle();
    if config.enable_data_collection {
        info!("Attempting to set user data sharing consent.");
        if let Ok(privacy) = connect_to_protocol_sync::<fsettings::PrivacyMarker>() {
            let privacy_settings = fsettings::PrivacySettings {
                user_data_sharing_consent: Some(true),
                ..Default::default()
            };
            match privacy.set(&privacy_settings, zx::MonotonicInstant::INFINITE) {
                Ok(Ok(())) => info!("Successfully set user data sharing consent."),
                Ok(Err(err)) => warn!("Could not set user data sharing consent: {err:?}"),
                Err(err) => warn!("Could not set user data sharing consent: {err:?}"),
            }
        } else {
            warn!("failed to connect to fuchsia.settings.Privacy");
        }
    }

    let kernels = Kernels::new();
    let mut fs = ServiceFs::new_local();

    let (sender, receiver) = async_channel::unbounded();
    run_proxy_thread(receiver);

    fs.dir("svc").add_fidl_service(Services::ComponentRunner);
    fs.dir("svc").add_fidl_service(Services::StarnixManager);
    fs.take_and_serve_directory_handle()?;
    let suspend_context = Arc::new(SuspendContext::default());
    fs.for_each_concurrent(None, |request: Services| async {
        match request {
            Services::ComponentRunner(stream) => {
                if let Err(e) = serve_component_runner(stream, &kernels).await {
                    error!(e:%; "failed to serve component runner");
                }
            }
            Services::StarnixManager(stream) => {
                if let Err(e) =
                    serve_starnix_manager(stream, suspend_context.clone(), &kernels, &sender).await
                {
                    error!(e:%; "failed to serve starnix manager");
                }
            }
        }
    })
    .await;
    Ok(())
}

async fn serve_component_runner(
    mut stream: frunner::ComponentRunnerRequestStream,
    kernels: &Kernels,
) -> Result<(), Error> {
    while let Some(event) = stream.next().await {
        match event.context("serving component runner")? {
            frunner::ComponentRunnerRequest::Start { start_info, controller, .. } => {
                kernels.start(start_info, controller).await?;
            }
            frunner::ComponentRunnerRequest::_UnknownMethod { ordinal, .. } => {
                warn!(ordinal:%; "Unknown ComponentRunner request");
            }
        }
    }
    Ok(())
}
