// Copyright 2019 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::{format_err, Error};

use serde_json::{from_value, to_value, Value};

use crate::setui::types::{IntlInfo, NetworkType, SetUiResult};
use fidl_fuchsia_media::AudioRenderUsage;
use fidl_fuchsia_settings::{
    self as fsettings, AudioMarker, AudioStreamSettingSource, AudioStreamSettings,
    ConfigurationInterfaces, DisplayMarker, DisplaySettings, IntlMarker, SetupMarker,
    SetupSettings, Volume,
};
use fuchsia_component::client::connect_to_service;
use fuchsia_syslog::macros::fx_log_info;

/// Facade providing access to SetUi interfaces.
#[derive(Debug)]
pub struct SetUiFacade {
    /// Audio proxy that may be optionally provided for testing. The proxy is not cached during
    /// normal operation.
    audio_proxy: Option<fsettings::AudioProxy>,

    /// Optional Display proxy for testing, similar to `audio_proxy`.
    display_proxy: Option<fsettings::DisplayProxy>,
}

impl SetUiFacade {
    pub fn new() -> SetUiFacade {
        SetUiFacade { audio_proxy: None, display_proxy: None }
    }

    /// Sets network option used by device setup.
    /// Same action as choosing "Setup over Ethernet [enabled|disabled]" in "Developer options"
    ///
    /// args: accepted args are "ethernet" or "wifi". ex: {"params": "ethernet"}
    pub async fn set_network(&self, args: Value) -> Result<Value, Error> {
        let network_type: NetworkType = from_value(args)?;
        fx_log_info!("set_network input {:?}", network_type);
        let setup_service_proxy = match connect_to_service::<SetupMarker>() {
            Ok(proxy) => proxy,
            Err(e) => bail!("Failed to connect to Setup service {:?}.", e),
        };

        let mut settings = SetupSettings::EMPTY;

        match network_type {
            NetworkType::Ethernet => {
                settings.enabled_configuration_interfaces = Some(ConfigurationInterfaces::Ethernet);
            }
            NetworkType::Wifi => {
                settings.enabled_configuration_interfaces = Some(ConfigurationInterfaces::Wifi);
            }
            _ => return Err(format_err!("Network type must either be ethernet or wifi.")),
        }
        // Update network configuration without automatic device reboot.
        // For changes to take effect, either restart basemgr component or reboot device.
        match setup_service_proxy.set2(settings, false).await? {
            Ok(_) => Ok(to_value(SetUiResult::Success)?),
            Err(err) => Err(format_err!("Update network settings failed with err {:?}", err)),
        }
    }

    /// Reports the network option used for setup
    ///
    /// Returns either "ethernet", "wifi" or "unknown".
    pub async fn get_network_setting(&self) -> Result<Value, Error> {
        let setup_service_proxy = match connect_to_service::<SetupMarker>() {
            Ok(proxy) => proxy,
            Err(e) => bail!("Failed to connect to Setup service {:?}.", e),
        };
        let setting = setup_service_proxy.watch().await?;
        match setting.enabled_configuration_interfaces {
            Some(ConfigurationInterfaces::Ethernet) => Ok(to_value(NetworkType::Ethernet)?),
            Some(ConfigurationInterfaces::Wifi) => Ok(to_value(NetworkType::Wifi)?),
            _ => Ok(to_value(NetworkType::Unknown)?),
        }
    }

    /// Sets Internationalization values.
    ///
    /// Input should is expected to be type IntlInfo in json.
    /// Example:
    /// {
    ///     "hour_cycle":"H12",
    ///     "locales":[{"id":"he-FR"}],
    ///     "temperature_unit":"Celsius",
    ///     "time_zone_id":"UTC"
    /// }
    pub async fn set_intl_setting(&self, args: Value) -> Result<Value, Error> {
        let intl_info: IntlInfo = from_value(args)?;
        fx_log_info!("Received Intl Settings Request {:?}", intl_info);

        let intl_service_proxy = match connect_to_service::<IntlMarker>() {
            Ok(proxy) => proxy,
            Err(e) => bail!("Failed to connect to Intl service {:?}.", e),
        };
        match intl_service_proxy.set(intl_info.into()).await? {
            Ok(_) => Ok(to_value(SetUiResult::Success)?),
            Err(err) => Err(format_err!("Update intl settings failed with err {:?}", err)),
        }
    }

    /// Reads the Internationalization setting.
    ///
    /// Returns IntlInfo in json.
    pub async fn get_intl_setting(&self) -> Result<Value, Error> {
        let intl_service_proxy = match connect_to_service::<IntlMarker>() {
            Ok(proxy) => proxy,
            Err(e) => bail!("Failed to connect to Intl service {:?}.", e),
        };
        let intl_info: IntlInfo = intl_service_proxy.watch().await?.into();
        return Ok(to_value(&intl_info)?);
    }

    /// Reports the AudioInput (mic muted) state.
    ///
    /// Returns true if mic is muted or false if mic is unmuted.
    pub async fn is_mic_muted(&self) -> Result<Value, Error> {
        let audio_proxy = match connect_to_service::<AudioMarker>() {
            Ok(proxy) => proxy,
            Err(e) => bail!("Failed to connect to Setup Audio service {:?}.", e),
        };
        match audio_proxy.watch().await?.input {
            Some(audio_input) => Ok(to_value(audio_input.muted)?),
            _ => Err(format_err!("Cannot read audio input.")),
        }
    }

    /// Sets the display brightness via `fuchsia.settings.Display.Set`.
    ///
    /// # Arguments
    /// * `args`: JSON value containing the desired brightness level as f32.
    pub async fn set_brightness(&self, args: Value) -> Result<Value, Error> {
        let brightness: f32 = from_value(args)?;

        // Use the test proxy if one was provided, otherwise connect to the discoverable Display
        // service.
        let display_proxy = match self.display_proxy.as_ref() {
            Some(proxy) => proxy.clone(),
            None => match connect_to_service::<DisplayMarker>() {
                Ok(proxy) => proxy,
                Err(e) => bail!("Failed to connect to Display service {:?}.", e),
            },
        };

        let settings = DisplaySettings {
            auto_brightness: Some(false),
            brightness_value: Some(brightness),
            ..DisplaySettings::EMPTY
        };
        match display_proxy.set(settings).await? {
            Ok(_) => Ok(to_value(SetUiResult::Success)?),
            Err(e) => Err(format_err!("SetBrightness failed with err {:?}", e)),
        }
    }

    /// Sets the media volume level via `fuchsia.settings.Audio.Set`.
    ///
    /// # Arguments
    /// * `args`: JSON value containing the desired volume level as f32.
    pub async fn set_media_volume(&self, args: Value) -> Result<Value, Error> {
        let volume: f32 = from_value(args)?;

        // Use the test proxy if one was provided, otherwise connect to the discoverable Audio
        // service.
        let audio_proxy = match self.audio_proxy.as_ref() {
            Some(proxy) => proxy.clone(),
            None => match connect_to_service::<AudioMarker>() {
                Ok(proxy) => proxy,
                Err(e) => bail!("Failed to connect to Display service {:?}.", e),
            },
        };

        let stream_settings = AudioStreamSettings {
            stream: Some(AudioRenderUsage::Media),
            source: Some(AudioStreamSettingSource::User),
            user_volume: Some(Volume { level: Some(volume), muted: Some(false), ..Volume::EMPTY }),
            ..AudioStreamSettings::EMPTY
        };
        let settings = fsettings::AudioSettings {
            streams: Some(vec![stream_settings]),
            input: None,
            ..fsettings::AudioSettings::EMPTY
        };

        match audio_proxy.set(settings).await? {
            Ok(_) => Ok(to_value(SetUiResult::Success)?),
            Err(e) => Err(format_err!("SetVolume failed with err {:?}", e)),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::common_utils::test::assert_value_round_trips_as;
    use crate::setui::types::{HourCycle, IntlInfo, LocaleId, TemperatureUnit};
    use fidl::endpoints::create_proxy_and_stream;
    use fuchsia_async as fasync;
    use futures::TryStreamExt;
    use serde_json::json;

    fn make_intl_info() -> IntlInfo {
        return IntlInfo {
            locales: Some(vec![LocaleId { id: "en-US".into() }]),
            temperature_unit: Some(TemperatureUnit::Celsius),
            time_zone_id: Some("UTC".into()),
            hour_cycle: Some(HourCycle::H12),
        };
    }

    #[test]
    fn serde_intl_set() {
        let intl_request = make_intl_info();
        assert_value_round_trips_as(
            intl_request,
            json!(
            {
                "locales": [{"id": "en-US"}],
                "temperature_unit":"Celsius",
                "time_zone_id": "UTC",
                "hour_cycle": "H12",
            }),
        );
    }

    // Tests that `set_brightness` correctly sends a request to the Display service.
    #[fasync::run_singlethreaded(test)]
    async fn test_set_brightness() {
        let brightness = 0.5f32;
        let (proxy, mut stream) = create_proxy_and_stream::<DisplayMarker>().unwrap();

        // Create a facade future that sends a request to `proxy`.
        let facade = SetUiFacade { audio_proxy: None, display_proxy: Some(proxy) };
        let facade_fut = async move {
            assert_eq!(
                facade.set_brightness(to_value(brightness).unwrap()).await.unwrap(),
                to_value(SetUiResult::Success).unwrap()
            );
        };

        // Create a future to service the request stream.
        let stream_fut = async move {
            match stream.try_next().await {
                Ok(Some(fsettings::DisplayRequest::Set { settings, responder })) => {
                    assert_eq!(
                        settings,
                        DisplaySettings {
                            auto_brightness: Some(false),
                            brightness_value: Some(brightness),
                            ..DisplaySettings::EMPTY
                        }
                    );
                    responder.send(&mut Ok(())).unwrap();
                }
                other => panic!("Unexpected stream item: {:?}", other),
            }
        };

        futures::future::join(facade_fut, stream_fut).await;
    }

    // Tests that `set_media_volume` correctly sends a request to the Audio service.
    #[fasync::run_singlethreaded(test)]
    async fn test_set_media_volume() {
        let volume = 0.5f32;
        let (proxy, mut stream) = create_proxy_and_stream::<AudioMarker>().unwrap();

        // Create a facade future that sends a request to `proxy`.
        let facade = SetUiFacade { audio_proxy: Some(proxy), display_proxy: None };
        let facade_fut = async move {
            assert_eq!(
                facade.set_media_volume(to_value(volume).unwrap()).await.unwrap(),
                to_value(SetUiResult::Success).unwrap()
            );
        };

        // Create a future to service the request stream.
        let stream_fut = async move {
            match stream.try_next().await {
                Ok(Some(fsettings::AudioRequest::Set { settings, responder })) => {
                    let mut streams = settings.streams.unwrap();
                    assert_eq!(1, streams.len());
                    assert_eq!(
                        streams.pop().unwrap(),
                        AudioStreamSettings {
                            stream: Some(AudioRenderUsage::Media),
                            source: Some(AudioStreamSettingSource::User),
                            user_volume: Some(Volume {
                                level: Some(volume),
                                muted: Some(false),
                                ..Volume::EMPTY
                            }),
                            ..AudioStreamSettings::EMPTY
                        }
                    );
                    responder.send(&mut Ok(())).unwrap();
                }
                other => panic!("Unexpected stream item: {:?}", other),
            }
        };

        futures::future::join(facade_fut, stream_fut).await;
    }
}
