// 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::{layout, trampoline};
use fidl::endpoints::{ClientEnd, Proxy};
use fidl::HandleBased;
use fidl_fuchsia_dash::LauncherError;
use fuchsia_component::client::connect_to_protocol;
use fuchsia_runtime::{HandleInfo as HandleId, HandleType};
use {
    fidl_fuchsia_hardware_pty as pty, fidl_fuchsia_io as fio, fidl_fuchsia_process as fproc,
    fuchsia_zircon as zx,
};

pub mod component;
pub mod package;

// -s: force input from stdin
// -i: force interactive
const DASH_ARGS_FOR_INTERACTIVE: [&[u8]; 2] = ["-i".as_bytes(), "-s".as_bytes()];
// TODO(https://fxbug.dev/42055812): Verbose (-v) or write-commands-to-stderr (-x) is required if a command is
// given, else it errors with `Can't open <cmd>`. -c: execute command
const DASH_ARGS_FOR_COMMAND: [&[u8]; 2] = ["-v".as_bytes(), "-c".as_bytes()];

async fn explore_over_handles(
    stdin: zx::Handle,
    stdout: zx::Handle,
    stderr: zx::Handle,
    mut tool_urls: Vec<String>,
    command: Option<String>,
    mut name_infos: Vec<fproc::NameInfo>,
    process_name: String,
    package_resolver: &crate::package_resolver::PackageResolver,
) -> Result<zx::Process, LauncherError> {
    // In addition to tools binaries requested by the user, add the built-in binaries of the
    // debug-dash-launcher package, creating `#!resolve` trampolines for all.
    tool_urls.push("fuchsia-pkg://fuchsia.com/debug-dash-launcher".into());
    let (tools_pkg_dir, tools_path) =
        trampoline::create_trampolines_from_packages(package_resolver, tool_urls).await?;
    layout::add_tools_to_name_infos(tools_pkg_dir, &mut name_infos);

    // The dash-launcher can be asked to launch multiple dash processes, each of which can make
    // their own process hierarchies. This will look better topologically if we make a child job for
    // each dash process.
    let job =
        fuchsia_runtime::job_default().create_child_job().map_err(|_| LauncherError::Internal)?;

    // Add handles for the current job, stdio, library loader and UTC time.
    let handle_infos = create_handle_infos(&job, stdin, stdout, stderr)?;

    let launcher = connect_to_protocol::<fproc::LauncherMarker>()
        .map_err(|_| LauncherError::ProcessLauncher)?;

    let mut args = Vec::new();
    if let Some(cmd) = command {
        args.extend(DASH_ARGS_FOR_COMMAND.iter().map(|b| b.to_vec()));
        args.push(cmd.into_bytes());
    } else {
        args.extend(DASH_ARGS_FOR_INTERACTIVE.iter().map(|b| b.to_vec()));
    };

    // Spawn the dash process.
    let info = create_launch_info(process_name, &job).await?;
    launcher.add_names(name_infos).map_err(|_| LauncherError::ProcessLauncher)?;
    launcher.add_handles(handle_infos).map_err(|_| LauncherError::ProcessLauncher)?;
    launcher.add_args(&args).map_err(|_| LauncherError::ProcessLauncher)?;
    let path_envvar = trampoline::create_env_path(tools_path);
    let env_vars = &[path_envvar.into_bytes()];
    launcher.add_environs(env_vars).map_err(|_| LauncherError::ProcessLauncher)?;
    let (status, process) =
        launcher.launch(info).await.map_err(|_| LauncherError::ProcessLauncher)?;
    zx::Status::ok(status).map_err(|_| LauncherError::ProcessLauncher)?;
    let process = process.ok_or(LauncherError::ProcessLauncher)?;

    // The job should be terminated when the dash process dies.
    job.set_critical(zx::JobCriticalOptions::empty(), &process)
        .map_err(|_| LauncherError::Internal)?;

    Ok(process)
}

fn split_pty_into_handles(
    pty: ClientEnd<pty::DeviceMarker>,
) -> Result<(zx::Handle, zx::Handle, zx::Handle), LauncherError> {
    let pty = pty.into_proxy().unwrap();

    // Split the PTY into 3 channels (stdin, stdout, stderr).
    let (stdout, to_pty_stdout) = fidl::endpoints::create_endpoints::<pty::DeviceMarker>();
    let (stderr, to_pty_stderr) = fidl::endpoints::create_endpoints::<pty::DeviceMarker>();
    let to_pty_stdout = to_pty_stdout.into_channel().into();
    let to_pty_stderr = to_pty_stderr.into_channel().into();

    // Clone the PTY to also be used for stdout and stderr.
    pty.clone2(to_pty_stdout).map_err(|_| LauncherError::Pty)?;
    pty.clone2(to_pty_stderr).map_err(|_| LauncherError::Pty)?;

    let stdin = pty.into_channel().unwrap().into_zx_channel().into_handle();
    let stdout = stdout.into_handle();
    let stderr = stderr.into_handle();

    Ok((stdin, stdout, stderr))
}

fn create_handle_infos(
    job: &zx::Job,
    stdin: zx::Handle,
    stdout: zx::Handle,
    stderr: zx::Handle,
) -> Result<Vec<fproc::HandleInfo>, LauncherError> {
    let stdin_handle = fproc::HandleInfo {
        handle: stdin.into_handle(),
        id: HandleId::new(HandleType::FileDescriptor, 0).as_raw(),
    };

    let stdout_handle = fproc::HandleInfo {
        handle: stdout.into_handle(),
        id: HandleId::new(HandleType::FileDescriptor, 1).as_raw(),
    };

    let stderr_handle = fproc::HandleInfo {
        handle: stderr.into_handle(),
        id: HandleId::new(HandleType::FileDescriptor, 2).as_raw(),
    };

    let job_dup =
        job.duplicate_handle(zx::Rights::SAME_RIGHTS).map_err(|_| LauncherError::Internal)?;
    let job_handle = fproc::HandleInfo {
        handle: zx::Handle::from(job_dup),
        id: HandleId::new(HandleType::DefaultJob, 0).as_raw(),
    };

    let ldsvc = fuchsia_runtime::loader_svc().map_err(|_| LauncherError::Internal)?;
    let ldsvc_handle =
        fproc::HandleInfo { handle: ldsvc, id: HandleId::new(HandleType::LdsvcLoader, 0).as_raw() };

    let utc_clock = {
        let utc_clock = fuchsia_runtime::duplicate_utc_clock_handle(zx::Rights::SAME_RIGHTS)
            .map_err(|_| LauncherError::Internal)?;
        utc_clock.into_handle()
    };
    let utc_clock_handle = fproc::HandleInfo {
        handle: utc_clock,
        id: HandleId::new(HandleType::ClockUtc, 0).as_raw(),
    };

    Ok(vec![stdin_handle, stdout_handle, stderr_handle, job_handle, ldsvc_handle, utc_clock_handle])
}

async fn create_launch_info(
    process_name: String,
    job: &zx::Job,
) -> Result<fproc::LaunchInfo, LauncherError> {
    // Load `/pkg/bin/sh` as an executable VMO and pass it to the Launcher.
    let dash_file = fuchsia_fs::file::open_in_namespace(
        "/pkg/bin/sh",
        fio::OpenFlags::RIGHT_EXECUTABLE | fio::OpenFlags::RIGHT_READABLE,
    )
    .map_err(|_| LauncherError::DashBinary)?;

    let executable = dash_file
        .get_backing_memory(
            fio::VmoFlags::READ | fio::VmoFlags::EXECUTE | fio::VmoFlags::PRIVATE_CLONE,
        )
        .await
        .map_err(|_| LauncherError::DashBinary)?
        .map_err(|_| LauncherError::DashBinary)?;

    let job_dup =
        job.duplicate_handle(zx::Rights::SAME_RIGHTS).map_err(|_| LauncherError::Internal)?;

    let name = truncate_str(&process_name, zx::sys::ZX_MAX_NAME_LEN).to_owned();

    Ok(fproc::LaunchInfo { name, job: job_dup, executable })
}

/// Truncates `s` to be at most `max_len` bytes.
fn truncate_str(s: &str, max_len: usize) -> &str {
    if s.len() <= max_len {
        return s;
    }
    // TODO(https://github.com/rust-lang/rust/issues/93743): Use floor_char_boundary when stable.
    let mut index = max_len;
    while index > 0 && !s.is_char_boundary(index) {
        index -= 1;
    }
    &s[..index]
}
