// Copyright 2020 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::log_if_err;
use crate::message::{Message, MessageReturn};
use crate::node::Node;
use crate::utils::connect_to_driver;
use anyhow::{format_err, Error};
use async_trait::async_trait;
use fidl_fuchsia_device as fdev;
use fuchsia_inspect::{self as inspect, NumericProperty, Property};
use fuchsia_zircon as zx;
use serde_derive::Deserialize;
use serde_json as json;
use std::collections::HashMap;
use std::rc::Rc;

/// Node: DeviceControlHandler
///
/// Summary: Provides an interface to control the power, performance, and sleep states of a devhost
///          device
///
/// Handles Messages:
///     - GetPerformanceState
///     - SetPerformanceState
///
/// Sends Messages: N/A
///
/// FIDL dependencies:
///     - fuchsia.device.Controller: the node uses this protocol to control the power, performance,
///       and sleep states of a devhost device

pub const MAX_PERF_STATES: u32 = fdev::MAX_DEVICE_PERFORMANCE_STATES;

/// A builder for constructing the DeviceControlhandler node
pub struct DeviceControlHandlerBuilder<'a> {
    driver_path: String,
    driver_proxy: Option<fdev::ControllerProxy>,
    inspect_root: Option<&'a inspect::Node>,
}

impl<'a> DeviceControlHandlerBuilder<'a> {
    pub fn new_with_driver_path(driver_path: String) -> Self {
        Self { driver_path, driver_proxy: None, inspect_root: None }
    }

    #[cfg(test)]
    pub fn new_with_proxy(driver_path: String, proxy: fdev::ControllerProxy) -> Self {
        Self { driver_path, driver_proxy: Some(proxy), inspect_root: None }
    }

    pub fn new_from_json(json_data: json::Value, _nodes: &HashMap<String, Rc<dyn Node>>) -> Self {
        #[derive(Deserialize)]
        struct Config {
            driver_path: String,
        }

        #[derive(Deserialize)]
        struct JsonData {
            config: Config,
        }

        let data: JsonData = json::from_value(json_data).unwrap();
        Self::new_with_driver_path(data.config.driver_path)
    }

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

    pub async fn build(self) -> Result<Rc<DeviceControlHandler>, Error> {
        // Optionally use the default proxy
        let proxy = if self.driver_proxy.is_none() {
            connect_to_driver::<fdev::ControllerMarker>(&self.driver_path).await?
        } else {
            self.driver_proxy.unwrap()
        };

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

        Ok(Rc::new(DeviceControlHandler {
            driver_path: self.driver_path.clone(),
            driver_proxy: proxy,
            inspect: InspectData::new(
                inspect_root,
                format!("DeviceControlHandler ({})", self.driver_path),
            ),
        }))
    }
}

pub struct DeviceControlHandler {
    driver_path: String,
    driver_proxy: fdev::ControllerProxy,

    /// A struct for managing Component Inspection data
    inspect: InspectData,
}

impl DeviceControlHandler {
    async fn handle_get_performance_state(&self) -> Result<MessageReturn, PowerManagerError> {
        fuchsia_trace::duration!(
            "power_manager",
            "DeviceControlHandler::handle_get_performance_state",
            "driver" => self.driver_path.as_str()
        );

        let result = self.get_performance_state().await;
        log_if_err!(result, "Failed to get performance state");
        fuchsia_trace::instant!(
            "power_manager",
            "DeviceControlHandler::get_performance_state_result",
            fuchsia_trace::Scope::Thread,
            "driver" => self.driver_path.as_str(),
            "result" => format!("{:?}", result).as_str()
        );

        match result {
            Ok(state) => Ok(MessageReturn::GetPerformanceState(state)),
            Err(e) => {
                self.inspect.get_performance_state_errors.add(1);
                Err(PowerManagerError::GenericError(e))
            }
        }
    }

    async fn get_performance_state(&self) -> Result<u32, Error> {
        let state =
            self.driver_proxy.get_current_performance_state().await.map_err(|e| {
                format_err!("{}: get_performance_state IPC failed: {}", self.name(), e)
            })?;

        Ok(state)
    }

    async fn handle_set_performance_state(
        &self,
        in_state: u32,
    ) -> Result<MessageReturn, PowerManagerError> {
        fuchsia_trace::duration!(
            "power_manager",
            "DeviceControlHandler::handle_set_performance_state",
            "driver" => self.driver_path.as_str(),
            "state" => in_state
        );

        let result = self.set_performance_state(in_state).await;
        log_if_err!(result, "Failed to set performance state");
        fuchsia_trace::instant!(
            "power_manager",
            "DeviceControlHandler::set_performance_state_result",
            fuchsia_trace::Scope::Thread,
            "driver" => self.driver_path.as_str(),
            "result" => format!("{:?}", result).as_str()
        );

        match result {
            Ok(_) => {
                self.inspect.perf_state.set(in_state.into());
                Ok(MessageReturn::SetPerformanceState)
            }
            Err(e) => {
                self.inspect.set_performance_state_errors.add(1);
                self.inspect.last_set_performance_state_error.set(format!("{}", e).as_str());
                Err(PowerManagerError::GenericError(e))
            }
        }
    }

    async fn set_performance_state(&self, in_state: u32) -> Result<(), Error> {
        // Make the FIDL call
        let (status, _out_state) =
            self.driver_proxy.set_performance_state(in_state).await.map_err(|e| {
                format_err!("{}: set_performance_state IPC failed: {}", self.name(), e)
            })?;

        // Check the status code
        zx::Status::ok(status).map_err(|e| {
            format_err!("{}: set_performance_state driver returned error: {}", self.name(), e)
        })?;

        Ok(())
    }
}

#[async_trait(?Send)]
impl Node for DeviceControlHandler {
    fn name(&self) -> String {
        format!("DeviceControlHandler ({})", self.driver_path)
    }

    async fn handle_message(&self, msg: &Message) -> Result<MessageReturn, PowerManagerError> {
        match msg {
            Message::GetPerformanceState => self.handle_get_performance_state().await,
            Message::SetPerformanceState(state) => self.handle_set_performance_state(*state).await,
            _ => Err(PowerManagerError::Unsupported),
        }
    }
}

struct InspectData {
    perf_state: inspect::UintProperty,
    get_performance_state_errors: inspect::UintProperty,
    set_performance_state_errors: inspect::UintProperty,
    last_set_performance_state_error: inspect::StringProperty,
}

impl InspectData {
    fn new(parent: &inspect::Node, name: String) -> Self {
        // Create a local root node and properties
        let root = parent.create_child(name);
        let perf_state = root.create_uint("performance_state", 0);
        let get_performance_state_errors = root.create_uint("get_performance_state_errors", 0);
        let set_performance_state_errors = root.create_uint("set_performance_state_errors", 0);
        let last_set_performance_state_error =
            root.create_string("last_set_performance_state_error", "");

        // Pass ownership of the new node to the parent node, otherwise it'll be dropped
        parent.record(root);

        InspectData {
            perf_state,
            get_performance_state_errors,
            set_performance_state_errors,
            last_set_performance_state_error,
        }
    }
}

#[cfg(test)]
pub mod tests {
    use super::*;
    use fuchsia_async as fasync;
    use futures::TryStreamExt;
    use inspect::assert_data_tree;
    use std::cell::Cell;

    pub fn setup_fake_driver(
        get_performance_state: impl Fn() -> u32 + 'static,
        mut set_performance_state: impl FnMut(u32) + 'static,
    ) -> fdev::ControllerProxy {
        let (proxy, mut stream) =
            fidl::endpoints::create_proxy_and_stream::<fdev::ControllerMarker>().unwrap();
        fasync::Task::local(async move {
            while let Ok(req) = stream.try_next().await {
                match req {
                    Some(fdev::ControllerRequest::GetCurrentPerformanceState { responder }) => {
                        let _ = responder.send(get_performance_state());
                    }
                    Some(fdev::ControllerRequest::SetPerformanceState {
                        requested_state,
                        responder,
                    }) => {
                        set_performance_state(requested_state as u32);
                        let _ = responder.send(zx::Status::OK.into_raw(), requested_state);
                    }
                    Some(other) => panic!("Unexpected request: {:?}", other),
                    None => return, // Client connection closed
                }
            }
        })
        .detach();

        proxy
    }

    pub async fn setup_test_node(
        get_performance_state: impl Fn() -> u32 + 'static,
        set_performance_state: impl FnMut(u32) + 'static,
    ) -> Rc<DeviceControlHandler> {
        DeviceControlHandlerBuilder::new_with_proxy(
            "Fake".to_string(),
            setup_fake_driver(get_performance_state, set_performance_state),
        )
        .build()
        .await
        .unwrap()
    }

    pub async fn setup_simple_test_node() -> Rc<DeviceControlHandler> {
        let perf_state = Rc::new(Cell::new(0));
        let perf_state_clone_1 = perf_state.clone();
        let perf_state_clone_2 = perf_state.clone();
        let get_performance_state = move || perf_state_clone_1.get();
        let set_performance_state = move |state| {
            perf_state_clone_2.set(state);
        };
        setup_test_node(get_performance_state, set_performance_state).await
    }

    /// Tests that an unsupported message is handled gracefully and an Unsupported error is returned
    #[fasync::run_singlethreaded(test)]
    async fn test_unsupported_msg() {
        let node = setup_simple_test_node().await;
        match node.handle_message(&Message::ReadTemperature).await {
            Err(PowerManagerError::Unsupported) => {}
            e => panic!("Unexpected return value: {:?}", e),
        }
    }

    /// Tests that the Get/SetPerformanceState messages cause the node to call the appropriate
    /// device controller FIDL APIs.
    #[fasync::run_singlethreaded(test)]
    async fn test_performance_state() {
        let node = setup_simple_test_node().await;

        // Send SetPerformanceState message to set a state of 1
        let commanded_perf_state = 1;
        match node
            .handle_message(&Message::SetPerformanceState(commanded_perf_state))
            .await
            .unwrap()
        {
            MessageReturn::SetPerformanceState => {}
            e => panic!("Unexpected return value: {:?}", e),
        }

        // Verify GetPerformanceState reads back the same state
        let received_perf_state =
            match node.handle_message(&Message::GetPerformanceState).await.unwrap() {
                MessageReturn::GetPerformanceState(state) => state,
                e => panic!("Unexpected return value: {:?}", e),
            };
        assert_eq!(commanded_perf_state, received_perf_state);

        // Send SetPerformanceState message to set a state of 2
        let commanded_perf_state = 2;
        match node
            .handle_message(&Message::SetPerformanceState(commanded_perf_state))
            .await
            .unwrap()
        {
            MessageReturn::SetPerformanceState => {}
            e => panic!("Unexpected return value: {:?}", e),
        }

        // Verify GetPerformanceState reads back the same state
        let received_perf_state =
            match node.handle_message(&Message::GetPerformanceState).await.unwrap() {
                MessageReturn::GetPerformanceState(state) => state,
                e => panic!("Unexpected return value: {:?}", e),
            };
        assert_eq!(commanded_perf_state, received_perf_state);
    }

    /// Tests for the presence and correctness of dynamically-added inspect data
    #[fasync::run_singlethreaded(test)]
    async fn test_inspect_data() {
        let inspector = inspect::Inspector::new();
        let _node = DeviceControlHandlerBuilder::new_with_proxy(
            "Fake".to_string(),
            fidl::endpoints::create_proxy::<fdev::ControllerMarker>().unwrap().0,
        )
        .with_inspect_root(inspector.root())
        .build()
        .await
        .unwrap();

        assert_data_tree!(
            inspector,
            root: {
                "DeviceControlHandler (Fake)": contains {}
            }
        );
    }

    /// Tests that well-formed configuration JSON does not panic the `new_from_json` function.
    #[fasync::run_singlethreaded(test)]
    async fn test_new_from_json() {
        let json_data = json::json!({
            "type": "DeviceControlHandler",
            "name": "dev_control",
            "config": {
                "driver_path": "/dev/class/cpu-ctrl/000"
            }
        });
        let _ = DeviceControlHandlerBuilder::new_from_json(json_data, &HashMap::new());
    }
}
