// 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 {
    crate::resolver,
    anyhow::{Context, Error},
    fidl::prelude::*,
    fidl_fuchsia_debugdata as fdebugdata, fidl_fuchsia_io as fio, fidl_fuchsia_sys as fv1sys,
    fuchsia_async as fasync,
    fuchsia_component::client::{connect_channel_to_protocol, connect_to_protocol},
    fuchsia_component::server::ServiceFs,
    fuchsia_component_test::LocalComponentHandles,
    fuchsia_zircon as zx,
    futures::{prelude::*, StreamExt},
    lazy_static::lazy_static,
    std::sync::{
        atomic::{AtomicU64, Ordering},
        Arc,
    },
    tracing::{debug, warn},
};

lazy_static! {
    static ref ENCLOSING_ENV_ID: AtomicU64 = AtomicU64::new(1);
}

/// Represents a single CFv1 environment.
/// Consumer of this protocol have no access to system services.
/// The logger provided to clients comes from isolated archivist.
/// TODO(82072): Support collection of inspect by isolated archivist.
struct EnclosingEnvironment {
    svc_task: Option<fasync::Task<()>>,
    env_controller_proxy: Option<fv1sys::EnvironmentControllerProxy>,
    env_proxy: fv1sys::EnvironmentProxy,
    service_directory: zx::Channel,
}

impl Drop for EnclosingEnvironment {
    fn drop(&mut self) {
        let svc_task = self.svc_task.take();
        let env_controller_proxy = self.env_controller_proxy.take();
        fasync::Task::spawn(async move {
            if let Some(svc_task) = svc_task {
                svc_task.cancel().await;
            }
            if let Some(env_controller_proxy) = env_controller_proxy {
                let _ = env_controller_proxy.kill().await;
            }
        })
        .detach();
    }
}

impl EnclosingEnvironment {
    fn new(
        incoming_svc: fio::DirectoryProxy,
        hermetic_test_package_name: Option<Arc<String>>,
    ) -> Result<Arc<Self>, Error> {
        let sys_env = connect_to_protocol::<fv1sys::EnvironmentMarker>()?;
        let (additional_svc, additional_directory_request) = zx::Channel::create()?;
        let incoming_svc = Arc::new(incoming_svc);
        let incoming_svc_clone = incoming_svc.clone();
        let mut fs = ServiceFs::new();
        let mut loader_tasks = vec![];
        let loader_service = connect_to_protocol::<fv1sys::LoaderMarker>()?;
        match hermetic_test_package_name {
            Some(hermetic_test_package_name) => {
                fs.add_fidl_service(move |stream: fv1sys::LoaderRequestStream| {
                    let hermetic_test_package_name = hermetic_test_package_name.clone();
                    let loader_service = loader_service.clone();
                    loader_tasks.push(fasync::Task::spawn(async move {
                        resolver::serve_hermetic_loader(
                            stream,
                            hermetic_test_package_name,
                            loader_service.clone(),
                        )
                        .await;
                    }));
                });
            }
            None => {
                fs.add_service_at(
                    fv1sys::LoaderMarker::PROTOCOL_NAME,
                    move |chan: fuchsia_zircon::Channel| {
                        if let Err(e) = connect_channel_to_protocol::<fv1sys::LoaderMarker>(chan) {
                            warn!("Cannot connect to loader: {}", e);
                        }
                        None
                    },
                );
            }
        }
        fs.add_service_at(
            fdebugdata::PublisherMarker::PROTOCOL_NAME,
            move |chan: fuchsia_zircon::Channel| {
                if let Err(e) = fdio::service_connect_at(
                    incoming_svc_clone.as_channel().as_ref(),
                    fdebugdata::PublisherMarker::PROTOCOL_NAME,
                    chan,
                ) {
                    warn!("cannot connect to debug data Publisher: {}", e);
                }
                None
            },
        )
        .add_service_at("fuchsia.logger.LogSink", move |chan: fuchsia_zircon::Channel| {
            if let Err(e) = fdio::service_connect_at(
                incoming_svc.as_channel().as_ref(),
                "fuchsia.logger.LogSink",
                chan,
            ) {
                warn!("cannot connect to LogSink: {}", e);
            }
            None
        });

        fs.serve_connection(additional_svc)?;
        let svc_task = fasync::Task::spawn(async move {
            fs.collect::<()>().await;
        });

        let mut service_list = fv1sys::ServiceList {
            names: vec![
                fv1sys::LoaderMarker::PROTOCOL_NAME.to_string(),
                fdebugdata::PublisherMarker::PROTOCOL_NAME.to_string(),
                "fuchsia.logger.LogSink".into(),
            ],
            provider: None,
            host_directory: Some(additional_directory_request),
        };

        let mut opts = fv1sys::EnvironmentOptions {
            inherit_parent_services: false,
            use_parent_runners: false,
            kill_on_oom: true,
            delete_storage_on_death: true,
        };

        let (env_proxy, env_server_end) = fidl::endpoints::create_proxy()?;
        let (service_directory, directory_request) = zx::Channel::create()?;

        let (env_controller_proxy, env_controller_server_end) = fidl::endpoints::create_proxy()?;
        let name = format!("env-{}", ENCLOSING_ENV_ID.fetch_add(1, Ordering::SeqCst));
        sys_env
            .create_nested_environment(
                env_server_end,
                env_controller_server_end,
                &name,
                Some(&mut service_list),
                &mut opts,
            )
            .context("Cannot create nested env")?;
        env_proxy.get_directory(directory_request).context("cannot get env directory")?;
        Ok(Self {
            svc_task: svc_task.into(),
            env_controller_proxy: env_controller_proxy.into(),
            env_proxy,
            service_directory,
        }
        .into())
    }

    fn get_launcher(&self, launcher: fidl::endpoints::ServerEnd<fv1sys::LauncherMarker>) {
        if let Err(e) = self.env_proxy.get_launcher(launcher) {
            warn!("GetLauncher failed: {}", e);
        }
    }

    fn connect_to_protocol(&self, protocol_name: &str, chan: zx::Channel) {
        if let Err(e) = fdio::service_connect_at(&self.service_directory, protocol_name, chan) {
            warn!("service_connect_at failed for {}: {}", protocol_name, e);
        }
    }

    async fn serve(&self, mut req_stream: fv1sys::EnvironmentRequestStream) {
        while let Some(req) = req_stream
            .try_next()
            .await
            .context("serving V1 stream failed")
            .map_err(|e| {
                warn!("{}", e);
            })
            .unwrap_or(None)
        {
            match req {
                fv1sys::EnvironmentRequest::GetLauncher { launcher, control_handle } => {
                    if let Err(e) = self.env_proxy.get_launcher(launcher) {
                        warn!("GetLauncher failed: {}", e);
                        control_handle.shutdown();
                    }
                }
                fv1sys::EnvironmentRequest::GetServices { services, control_handle } => {
                    if let Err(e) = self.env_proxy.get_services(services) {
                        warn!("GetServices failed: {}", e);

                        control_handle.shutdown();
                    }
                }
                fv1sys::EnvironmentRequest::GetDirectory { directory_request, control_handle } => {
                    if let Err(e) = self.env_proxy.get_directory(directory_request) {
                        warn!("GetDirectory failed: {}", e);
                        control_handle.shutdown();
                    }
                }
                fv1sys::EnvironmentRequest::CreateNestedEnvironment {
                    environment,
                    controller,
                    label,
                    mut additional_services,
                    mut options,
                    control_handle,
                } => {
                    let services = match &mut additional_services {
                        Some(s) => s.as_mut().into(),
                        None => None,
                    };
                    if let Err(e) = self.env_proxy.create_nested_environment(
                        environment,
                        controller,
                        &label,
                        services,
                        &mut options,
                    ) {
                        warn!("CreateNestedEnvironment failed: {}", e);
                        control_handle.shutdown();
                    }
                }
            }
        }
    }
}

/// Create a new and single enclosing env for every test. Each test only gets a single enclosing env
/// no matter how many times it connects to Environment service.
pub async fn gen_enclosing_env(
    handles: LocalComponentHandles,
    hermetic_test_package_name: Option<Arc<String>>,
) -> Result<(), Error> {
    // This function should only be called when test tries to connect to Environment or Launcher.
    let mut fs = ServiceFs::new();
    let incoming_svc = handles.clone_from_namespace("svc")?;
    let enclosing_env = EnclosingEnvironment::new(incoming_svc, hermetic_test_package_name)
        .context("Cannot create enclosing env")?;
    let enclosing_env_clone = enclosing_env.clone();
    let enclosing_env_clone2 = enclosing_env.clone();

    fs.dir("svc")
        .add_fidl_service(move |req_stream: fv1sys::EnvironmentRequestStream| {
            debug!("Received Env connection request");
            let enclosing_env = enclosing_env.clone();
            fasync::Task::spawn(async move {
                enclosing_env.serve(req_stream).await;
            })
            .detach();
        })
        .add_service_at(
            fv1sys::LauncherMarker::PROTOCOL_NAME,
            move |chan: fuchsia_zircon::Channel| {
                enclosing_env_clone.get_launcher(chan.into());
                None
            },
        )
        .add_service_at(
            fv1sys::LoaderMarker::PROTOCOL_NAME,
            move |chan: fuchsia_zircon::Channel| {
                enclosing_env_clone2.connect_to_protocol(fv1sys::LoaderMarker::PROTOCOL_NAME, chan);
                None
            },
        );

    fs.serve_connection(handles.outgoing_dir.into_channel())?;
    fs.collect::<()>().await;

    // TODO(fxbug.dev/82021): kill and clean environment
    Ok(())
}
