// 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::log_if_err,
    crate::message::Message,
    crate::node::Node,
    anyhow::{format_err, Context, Result},
    async_trait::async_trait,
    async_utils::hanging_get::client::HangingGetStream,
    fidl_fuchsia_settings as fsettings,
    fuchsia_component::client::connect_to_protocol,
    fuchsia_inspect::{self as inspect, Property},
    futures::future::{FutureExt as _, LocalBoxFuture},
    futures::stream::FuturesUnordered,
    futures::StreamExt as _,
    serde_derive::Deserialize,
    serde_json as json,
    std::collections::HashMap,
    std::rc::Rc,
};

/// Node: InputSettingsHandler
///
/// Summary: Connects to the fuchsia.settings.Input service to monitor for input settings changes.
///          (Initially, the node is only concerned with monitoring the enabled state of the
///          microphone). The node relays these settings changes to the SystemProfileHandler node.
///
/// Handles Messages: N/A
///
/// Sends Messages:
///     - NotifyMicEnabledChanged
///
/// FIDL dependencies:
///     - fuchsia.settings.Input: the node connects to this service to monitor for changes to input
///       settings

pub struct InputSettingsHandlerBuilder<'a> {
    profile_handler_node: Rc<dyn Node>,
    input_settings_proxy: Option<fsettings::InputProxy>,
    inspect_root: Option<&'a inspect::Node>,
}

impl<'a> InputSettingsHandlerBuilder<'a> {
    pub fn new_from_json(json_data: json::Value, nodes: &HashMap<String, Rc<dyn Node>>) -> Self {
        #[derive(Deserialize)]
        struct Dependencies {
            system_profile_handler_node: String,
        }

        #[derive(Deserialize)]
        struct JsonData {
            dependencies: Dependencies,
        }

        let data: JsonData = json::from_value(json_data).unwrap();
        Self {
            profile_handler_node: nodes[&data.dependencies.system_profile_handler_node].clone(),
            input_settings_proxy: None,
            inspect_root: None,
        }
    }

    #[cfg(test)]
    fn new(profile_handler_node: Rc<dyn Node>) -> Self {
        Self { profile_handler_node, input_settings_proxy: None, inspect_root: None }
    }

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

    #[cfg(test)]
    fn with_proxy(mut self, proxy: fsettings::InputProxy) -> Self {
        self.input_settings_proxy = Some(proxy);
        self
    }

    pub fn build(
        self,
        futures_out: &FuturesUnordered<LocalBoxFuture<'_, ()>>,
    ) -> Result<Rc<InputSettingsHandler>> {
        // Allow test to override
        let inspect_root =
            self.inspect_root.unwrap_or_else(|| inspect::component::inspector().root());
        let inspect = InspectData::new(inspect_root, "InputSettingsHandler".to_string());

        // Allow test to override
        let input_settings_proxy = if let Some(proxy) = self.input_settings_proxy {
            proxy
        } else {
            connect_to_protocol::<fsettings::InputMarker>()?
        };

        let node = Rc::new(InputSettingsHandler {
            input_settings_proxy,
            profile_handler_node: self.profile_handler_node,
            inspect,
        });

        futures_out.push(node.clone().watch_input_settings()?);

        Ok(node)
    }
}

pub struct InputSettingsHandler {
    /// Proxy to the fuchsia.settings.Input service.
    input_settings_proxy: fsettings::InputProxy,

    /// Node that we send the NotifyMicEnabledChanged message to once we observe changes to the
    /// input settings.
    profile_handler_node: Rc<dyn Node>,

    inspect: InspectData,
}

impl InputSettingsHandler {
    /// Watch the Input settings service for changes. When changes to the microphone enabled state
    /// are observed, a NotifyMicEnabledChanged message is sent to `profile_handler_node`. The
    /// method returns a Future that performs these steps in an infinite loop.
    fn watch_input_settings<'a>(self: Rc<Self>) -> Result<LocalBoxFuture<'a, ()>> {
        // Create a HangingGetStream wrapper to abstract the details of the hanging-get pattern that
        // is used by the InputSettings service.
        let proxy = self.input_settings_proxy.clone();
        let mut stream = HangingGetStream::new(proxy, fsettings::InputProxy::watch);

        Ok(async move {
            self.inspect.set_handler_enabled(true);
            let mut prev_mic_enabled = None;
            loop {
                match stream.next().await {
                    // Got a settings change event
                    Some(Ok(settings)) => match Self::parse_is_mic_enabled(settings) {
                        Ok(enabled) => {
                            if prev_mic_enabled != Some(enabled) {
                                self.inspect.set_mic_enabled(enabled);
                                prev_mic_enabled = Some(enabled);
                                log_if_err!(
                                    self.send_message(
                                        &self.profile_handler_node,
                                        &Message::NotifyMicEnabledChanged(enabled),
                                    )
                                    .await,
                                    "Failed to send NotifyMicEnabledChanged"
                                );
                            }
                        }
                        Err(e) => log::error!("Failed to parse mic settings: {:?}", e),
                    },

                    // Stream gave an unexpected error. This should only happen if the InputSettings
                    // service is not available (likely because it isn't running on this build
                    // variant), so exit the loop.
                    Some(Err(e)) => {
                        log::error!("Failed to monitor fuchsia.settings.Input ({:?})", e);
                        break;
                    }

                    // Stream will never close because the HangingGetStream always polls for new
                    // data.
                    None => unreachable!(),
                }
            }

            log::error!("InputSettingsHandler is disabled");
            self.inspect.set_handler_enabled(false);
        }
        .boxed_local())
    }

    /// Parses the InputSettings struct to retrieve microphone enabled state.
    fn parse_is_mic_enabled(settings: fsettings::InputSettings) -> Result<bool> {
        let mic_settings = settings
            .devices
            .context("Missing 'devices' in settings")?
            .into_iter()
            .filter(|device| device.device_type == Some(fsettings::DeviceType::Microphone))
            .collect::<Vec<_>>();

        match mic_settings.len() {
            0 => Err(format_err!("Missing microphone settings")),
            1 => Ok(()),
            n => Err(format_err!("Invalid microphone settings length {} (expected 1)", n)),
        }?;

        let is_enabled = mic_settings[0]
            .state
            .as_ref()
            .ok_or(format_err!("Microphone DeviceState is None"))?
            .toggle_flags
            .ok_or(format_err!("Microphone ToggleStateFlags is None"))?
            .contains(fsettings::ToggleStateFlags::AVAILABLE);

        Ok(is_enabled)
    }
}

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

struct InspectData {
    handler_enabled: inspect::StringProperty,
    mic_enabled: inspect::StringProperty,
}

impl InspectData {
    fn new(parent: &inspect::Node, name: String) -> Self {
        let root = parent.create_child(name);
        let handler_enabled = root.create_string("handler_enabled", "");
        let mic_enabled = root.create_string("mic_enabled", "");
        parent.record(root);
        Self { handler_enabled, mic_enabled }
    }

    fn set_handler_enabled(&self, enabled: bool) {
        self.handler_enabled.set(&enabled.to_string());
    }

    fn set_mic_enabled(&self, enabled: bool) {
        self.mic_enabled.set(&enabled.to_string());
    }
}

#[cfg(test)]
mod tests {
    use {
        super::*,
        crate::test::mock_node::{create_dummy_node, MessageMatcher, MockNodeMaker},
        crate::{msg_eq, msg_ok_return},
        fuchsia_async as fasync,
        fuchsia_inspect::assert_data_tree,
    };

    // A fake Settings service implementation for testing
    struct FakeSettingsSvc {
        stream: fsettings::InputRequestStream,
        pending_request: Option<fsettings::InputWatchResponder>,
    }
    impl FakeSettingsSvc {
        fn new() -> (fsettings::InputProxy, Self) {
            let (proxy, stream) =
                fidl::endpoints::create_proxy_and_stream::<fsettings::InputMarker>()
                    .expect("Failed to create Input proxy and stream");
            (proxy, Self { stream, pending_request: None })
        }

        // Generates the required InputSettings struct based on some short parameters for testing
        fn generate_device_settings(mic_enabled: bool) -> fsettings::InputSettings {
            fsettings::InputSettings {
                devices: Some(vec![fsettings::InputDevice {
                    device_type: Some(fsettings::DeviceType::Microphone),
                    state: Some(fsettings::DeviceState {
                        toggle_flags: Some(if mic_enabled {
                            fsettings::ToggleStateFlags::AVAILABLE
                        } else {
                            fsettings::ToggleStateFlags::MUTED
                        }),
                        ..fsettings::DeviceState::EMPTY
                    }),
                    ..fsettings::InputDevice::EMPTY
                }]),
                ..fsettings::InputSettings::EMPTY
            }
        }

        // Gets the pending hanging-get request and completes the request with the specified device
        // settings. Waits for the next hanging-get request to arrive before returning to ensure the
        // node has processed the response.
        async fn set_mic_enabled(&mut self, enabled: bool) {
            // Make sure there is a pending hanging-get
            self.ensure_request_pending().await;

            // Complete the pending hanging-get with the mic_enabled value
            self.pending_request
                .take()
                .unwrap()
                .send(Self::generate_device_settings(enabled))
                .expect("Failed to send mic state update to client");

            // Wait for the next hanging-get request to arrive so we can be sure the node has
            // processed the mic_enabled result we just provided
            self.ensure_request_pending().await;
        }

        async fn ensure_request_pending(&mut self) {
            if self.pending_request.is_none() {
                self.pending_request = Some(self.get_next_request().await);
            }
        }

        // Retrieves the next hanging-get request
        async fn get_next_request(&mut self) -> fsettings::InputWatchResponder {
            match self
                .stream
                .next()
                .await
                .expect(
                    "Input request stream yielded Some(None)
                    (Input channel closed without receiving hanging-get request)",
                )
                .expect("Input request stream yielded Some(Err)")
            {
                fsettings::InputRequest::Watch { responder } => responder,
                request => panic!("Unexpected request: {:?}", request),
            }
        }
    }

    /// 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 (proxy, mut fake_settings) = FakeSettingsSvc::new();
        let futures_out = FuturesUnordered::new();
        let _node = InputSettingsHandlerBuilder::new(create_dummy_node())
            .with_inspect_root(inspector.root())
            .with_proxy(proxy)
            .build(&futures_out)
            .unwrap();

        futures::select! {
            _ = futures_out.collect::<()>() => {},
            _ = async {
                fake_settings.set_mic_enabled(true).await;
                assert_data_tree!(
                    inspector,
                    root: {
                        "InputSettingsHandler": {
                            "handler_enabled": "true",
                            "mic_enabled": "true"
                        }
                    }
                );

                fake_settings.set_mic_enabled(false).await;
                assert_data_tree!(
                    inspector,
                    root: {
                        "InputSettingsHandler": {
                            "handler_enabled": "true",
                            "mic_enabled": "false"
                        }
                    }
                );
            }.fuse() => {}
        };
    }

    /// Tests that the InputSettingsHandler relays NotifyMicEnabledChanged messages to the
    /// ProfileHandler node when it observes changes to input settings.
    #[fasync::run_singlethreaded(test)]
    async fn test_settings_monitor() {
        let mut mock_maker = MockNodeMaker::new();

        // For this test, the ProfileHandler should receive two NotifyMicEnabledChanged messages
        let profile_handler_node = mock_maker.make(
            "ProfileHandler",
            vec![
                (msg_eq!(NotifyMicEnabledChanged(true)), msg_ok_return!(NotifyMicEnabledChanged)),
                (msg_eq!(NotifyMicEnabledChanged(false)), msg_ok_return!(NotifyMicEnabledChanged)),
            ],
        );

        // Create the node
        let (proxy, mut fake_settings) = FakeSettingsSvc::new();
        let futures_out = FuturesUnordered::new();
        let _node = InputSettingsHandlerBuilder::new(profile_handler_node)
            .with_proxy(proxy)
            .build(&futures_out);

        // Use `select!` here so that the node future is polled concurrently with our fake_settings
        // changes. This lets the node's `watch_input_settings` future run while we simulate input
        // settings changes.
        futures::select! {
            _ = futures_out.collect::<()>() => {},
            _ = async {
                fake_settings.set_mic_enabled(true).await;
                fake_settings.set_mic_enabled(false).await;
            }.fuse() => {}
        };

        // When mock_maker goes out of scope it verifies the two NotifyMicEnabledChanged messages
        // were received
    }
}
