// 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 anyhow::{anyhow, Context, Error};
use fidl_fuchsia_io::{DirectoryProxy, NodeAttributes, OpenFlags};
use fuchsia_fs::directory::{open_directory, open_file, readdir, DirentKind};
use fuchsia_zircon as zx;
use futures::future::BoxFuture;
use futures::{FutureExt, TryFutureExt};

pub async fn register_migration_status(root: &fuchsia_inspect::Node, status: zx::Status) {
    match status {
        zx::Status::OK => {
            root.record_uint("migration_status:success", 1);
        }
        zx::Status::NO_SPACE => {
            root.record_uint("migration_status:out_of_space", 1);
        }
        _ => {
            root.record_uint("migration_status:other_error", 1);
        }
    }
}

pub async fn register_stats(root: &fuchsia_inspect::Node, data_dir: DirectoryProxy) {
    root.record_lazy_child("data_stats", move || {
        let data_dir = Clone::clone(&data_dir);
        async move {
            let inspector = fuchsia_inspect::Inspector::default();
            let root = inspector.root();

            // Filesystem info stats
            let stats_node = root.create_child("stats");
            record_filesystem_info(&stats_node, &data_dir).await?;
            root.record(stats_node);

            // Tree size stats
            let tree_size_node = root.create_child("data");
            record_tree_size(tree_size_node.clone_weak(), data_dir).await?;
            root.record(tree_size_node);

            Ok(inspector)
        }
        .or_else(|e: Error| async move {
            let inspector = fuchsia_inspect::Inspector::default();
            let root = inspector.root();
            root.record_string(
                "error",
                format!("Failed to collect fshost inspect metrics: {:?}", e),
            );
            Ok(inspector)
        })
        .boxed()
    });
}

/// Records filesystem information
async fn record_filesystem_info(
    stats_node: &fuchsia_inspect::Node,
    data_dir: &DirectoryProxy,
) -> Result<(), Error> {
    let (status, info_wrapped) =
        data_dir.query_filesystem().await.context("Transport error on query_filesystem")?;
    zx::Status::ok(status).context("query_filesystem failed")?;
    let info = info_wrapped.ok_or(anyhow!("failed to get filesystem info"))?;
    stats_node.record_uint("fvm_free_bytes", info.free_shared_pool_bytes);
    stats_node.record_uint("allocated_inodes", info.total_nodes);
    stats_node.record_uint("used_inodes", info.used_nodes);
    // Total bytes is the size of the partition plus the size it could conceivably grow into.
    // TODO(https://fxbug.dev/42165435): Remove this misleading metric.
    stats_node.record_uint("total_bytes", info.total_bytes + info.free_shared_pool_bytes);
    stats_node.record_uint("allocated_bytes", info.total_bytes);
    stats_node.record_uint("used_bytes", info.used_bytes);
    Ok(())
}

/// Records metrics for the size of each file/directory in the data filesystem's directory hierarchy
fn record_tree_size(
    node: fuchsia_inspect::Node,
    dir_proxy: DirectoryProxy,
) -> BoxFuture<'static, Result<TreeSize, Error>> {
    async move {
        let mut total: TreeSize = Default::default();
        for dir_entry in readdir(&dir_proxy).await?.iter() {
            match dir_entry.kind {
                DirentKind::File => {
                    let child = node.create_child(&dir_entry.name);
                    let file_proxy =
                        open_file(&dir_proxy, &dir_entry.name, OpenFlags::RIGHT_READABLE).await?;
                    let attrs = file_proxy
                        .get_attr()
                        .await
                        .map(|(status, attrs)| zx::Status::ok(status).map(|_| attrs))??;
                    let size: TreeSize = attrs.into();
                    size.record(&child);
                    node.record(child);
                    total += size;
                }
                DirentKind::Directory => {
                    let child = node.create_child(&dir_entry.name);
                    let directory_proxy =
                        open_directory(&dir_proxy, &dir_entry.name, OpenFlags::RIGHT_READABLE)
                            .await
                            .context("open_directory failed")?;
                    let size = record_tree_size(child.clone_weak(), directory_proxy).await?;
                    total += size;
                    node.record(child);
                }
                _ => continue,
            }
        }
        total.record(&node);
        Ok(total)
    }
    .boxed()
}

#[derive(Default)]
struct TreeSize {
    content_size: u64,
    storage_size: u64,
}

impl TreeSize {
    // NOTE: Use caution when changing the names of these Inspect properties, there may be out of
    // tree users depending on these values.
    const CONTENT_SIZE_PROP_NAME: &'static str = "size";
    const STORAGE_SIZE_PROP_NAME: &'static str = "storage_size";

    fn record(&self, node: &fuchsia_inspect::Node) {
        node.record_uint(Self::CONTENT_SIZE_PROP_NAME, self.content_size);
        node.record_uint(Self::STORAGE_SIZE_PROP_NAME, self.storage_size);
    }
}

impl From<NodeAttributes> for TreeSize {
    fn from(value: NodeAttributes) -> Self {
        Self { content_size: value.content_size, storage_size: value.storage_size }
    }
}

impl std::ops::AddAssign for TreeSize {
    fn add_assign(&mut self, rhs: Self) {
        self.content_size += rhs.content_size;
        self.storage_size += rhs.storage_size;
    }
}
