// 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 crate::error::PowerManagerError;
use crate::message::{Message, MessageResult, MessageReturn};
use crate::node::Node;
use anyhow::{format_err, Error};
use async_trait::async_trait;
use fidl_fuchsia_kernel as fkernel;
use fuchsia_inspect::{self as inspect, NumericProperty as _, Property as _};
use fuchsia_zircon::sys;
use fuchsia_zircon::{self as zx, prelude::AsHandleRef};
use std::rc::Rc;

/// Node: SyscallHandler
///
/// Summary: Executes syscalls so that these calls can be easily mocked by tests for dependent
///          nodes.
///
/// Handles Messages:
///     - GetNumCpus
///     - SetCpuPerformanceInfo
///
/// FIDL dependencies: None

#[derive(Default)]
pub struct SyscallHandlerBuilder<'a> {
    /// A fake CPU resource for injection into SyscallHandler.
    cpu_resource: Option<zx::Resource>,

    /// A fake Inspect root for injection into Syscall Handler.
    inspect_root: Option<&'a inspect::Node>,
}

impl<'a> SyscallHandlerBuilder<'a> {
    pub fn new() -> Self {
        Self::default()
    }

    #[cfg(test)]
    fn with_cpu_resource(mut self, resource: zx::Resource) -> Self {
        self.cpu_resource = Some(resource);
        self
    }

    #[cfg(test)]
    fn with_inspect_root(mut self, root: &'a inspect::Node) -> Self {
        self.inspect_root = Some(root);
        self
    }

    pub async fn build(self) -> Result<Rc<SyscallHandler>, Error> {
        // If a CPU resource was not provided, query component_manager for it.
        let cpu_resource = match self.cpu_resource {
            Some(resource) => resource,
            None => {
                let proxy =
                    fuchsia_component::client::connect_to_protocol::<fkernel::CpuResourceMarker>()?;
                proxy.get().await?
            }
        };

        // Optionally use the default inspect root node
        let inspect_root = self.inspect_root.unwrap_or(inspect::component::inspector().root());

        let inspect_data = InspectData::new(inspect_root, "SyscallHandler");

        Ok(Rc::new(SyscallHandler { cpu_resource, inspect: inspect_data }))
    }
}

/// Struct for handling syscalls.
pub struct SyscallHandler {
    cpu_resource: zx::Resource,
    inspect: InspectData,
}

impl SyscallHandler {
    fn handle_get_num_cpus(&self) -> MessageResult {
        // There are no assumptions made by this unsafe block; it is only unsafe due to FFI.
        let num_cpus = unsafe { sys::zx_system_get_num_cpus() };

        Ok(MessageReturn::GetNumCpus(num_cpus))
    }

    fn handle_set_cpu_performance_info(
        &self,
        new_info: &Vec<sys::zx_cpu_performance_info_t>,
    ) -> MessageResult {
        // The unsafe block assumes only that the pointer to `new_info` agrees with the count
        // argument that follows.
        let status = unsafe {
            sys::zx_system_set_performance_info(
                self.cpu_resource.raw_handle(),
                sys::ZX_CPU_PERF_SCALE,
                new_info.as_ptr() as *const u8,
                new_info.len(),
            )
        };

        if let Err(e) = zx::Status::ok(status) {
            self.inspect.set_performance_info_error_count.add(1);
            let error_string = e.to_string();
            self.inspect.set_performance_info_last_error.set(&error_string);
            let verbose_string = format!(
                "{}: zx_system_set_performance_info returned error: {}",
                self.name(),
                &error_string
            );
            log::error!("{}", &verbose_string);
            return Err(format_err!("{}", &verbose_string).into());
        }

        Ok(MessageReturn::SetCpuPerformanceInfo)
    }
}

#[async_trait(?Send)]
impl Node for SyscallHandler {
    fn name(&self) -> String {
        "SyscallHandler".to_string()
    }

    async fn handle_message(&self, msg: &Message) -> MessageResult {
        match msg {
            Message::GetNumCpus => self.handle_get_num_cpus(),
            Message::SetCpuPerformanceInfo(new_info) => {
                self.handle_set_cpu_performance_info(new_info)
            }
            _ => Err(PowerManagerError::Unsupported),
        }
    }
}

struct InspectData {
    _root_node: inspect::Node,

    // Properties
    set_performance_info_error_count: inspect::UintProperty,
    set_performance_info_last_error: inspect::StringProperty,
}

impl InspectData {
    fn new(parent: &inspect::Node, node_name: &str) -> Self {
        let root_node = parent.create_child(node_name);

        let set_performance_info = root_node.create_child("zx_system_set_performance_info");
        let set_performance_info_error_count = set_performance_info.create_uint("error_count", 0);
        let set_performance_info_last_error =
            set_performance_info.create_string("last_error", "<None>");
        root_node.record(set_performance_info);

        Self {
            _root_node: root_node,
            set_performance_info_error_count,
            set_performance_info_last_error,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use fuchsia_async as fasync;
    use inspect::assert_data_tree;

    // Tests that errors are logged to Inspect as expected.
    #[fasync::run_singlethreaded(test)]
    async fn test_inspect_data() {
        let resource = zx::Handle::invalid().into();
        let inspector = inspect::Inspector::new();
        let builder = SyscallHandlerBuilder::new()
            .with_cpu_resource(resource)
            .with_inspect_root(inspector.root());
        let handler = builder.build().await.unwrap();

        // The test links against a fake implementation of zx_system_set_performance_info that is
        // hard-coded to return ZX_ERR_BAD_HANDLE.
        let status_string = zx::Status::BAD_HANDLE.to_string();

        match handler.handle_message(&Message::SetCpuPerformanceInfo(Vec::new())).await {
            Ok(_) => panic!("Expected to receive an error"),
            Err(PowerManagerError::GenericError(e)) => {
                assert!(e.to_string().contains(&status_string));
            }
            Err(e) => panic!("Expected GenericError; received {:?}", e),
        }

        assert_data_tree!(
            inspector,
            root: {
                SyscallHandler: {
                    zx_system_set_performance_info: {
                        error_count: 1u64,
                        last_error: status_string,
                    }
                }
            }
        );
    }
}
