// Copyright 2023 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::device::BlockDevice;
use crate::environment::{Filesystem, FilesystemLauncher};
use anyhow::{Context, Error, Result};
use fidl_fuchsia_device::ControllerProxy;
use fs_management::filesystem::ServingMultiVolumeFilesystem;
use fs_management::format::DiskFormat;
use fs_management::partition::{find_partition, PartitionMatcher};
use fuchsia_zircon::{self as zx, Duration};
use futures::StreamExt;
use std::sync::Arc;
use vfs::service;

/// Make a new vfs service node that implements fuchsia.update.verify.BlobfsVerifier
pub fn blobfs_verifier_service() -> Arc<service::Service> {
    service::host(
        move |mut stream: fidl_fuchsia_update_verify::BlobfsVerifierRequestStream| async move {
            while let Some(request) = stream.next().await {
                match request {
                    Ok(fidl_fuchsia_update_verify::BlobfsVerifierRequest::Verify {
                        responder,
                        ..
                    }) => {
                        // TODO(https://fxbug.dev/42077105): Implement by calling out to Fxfs' blob volume.
                        responder.send(Ok(())).unwrap_or_else(|e| {
                            tracing::error!("failed to send Verify response. error: {:?}", e);
                        });
                    }
                    Err(e) => {
                        tracing::error!("BlobfsVerifier server failed: {:?}", e);
                        return;
                    }
                }
            }
        },
    )
}

const FIND_PARTITION_DURATION: Duration = Duration::from_seconds(10);

async fn find_fxblob_partition(ramdisk_prefix: Option<String>) -> Result<ControllerProxy, Error> {
    let matcher = PartitionMatcher {
        detected_disk_formats: Some(vec![DiskFormat::Fxfs]),
        ignore_prefix: ramdisk_prefix,
        ..Default::default()
    };

    find_partition(matcher, FIND_PARTITION_DURATION).await.context("failed to find Fxfs")
}

/// Mounts (or formats) the data volume in Fxblob.  Assumes the partition is already formatted.
pub async fn mount_or_format_data(
    ramdisk_prefix: Option<String>,
    launcher: &FilesystemLauncher,
) -> Result<(ServingMultiVolumeFilesystem, Filesystem), Error> {
    let partition_controller = find_fxblob_partition(ramdisk_prefix).await?;
    let partition_path = partition_controller
        .get_topological_path()
        .await
        .context("get_topo_path transport error")?
        .map_err(zx::Status::from_raw)
        .context("get_topo_path returned error")?;
    tracing::info!(%partition_path, "Found Fxblob partition");
    let mut device = Box::new(
        BlockDevice::from_proxy(partition_controller, &partition_path)
            .await
            .context("failed to make new device")?,
    );
    let mut filesystem = launcher.serve_fxblob(device.as_mut()).await.context("serving Fxblob")?;
    let data =
        launcher.serve_data_fxblob(&mut filesystem).await.context("serving data from Fxblob")?;

    Ok((filesystem, data))
}
