// 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 super::types::{
    ConnectivityState, DeviceStateDto, MacAddressFilterSettingsDto, NeighborInfoDto,
};
use crate::common_utils::lowpan_context::LowpanContext;
use anyhow::Error;
use fidl_fuchsia_lowpan_device::{DeviceExtraProxy, DeviceProxy};
use fidl_fuchsia_lowpan_test::DeviceTestProxy;
use fuchsia_sync::RwLock;

/// Perform Wpan FIDL operations.
///
/// Note this object is shared among all threads created by server.
#[derive(Debug)]
pub struct WpanFacade {
    /// The proxy to access the lowpan Device service.
    device: RwLock<Option<DeviceProxy>>,
    /// The proxy to access the lowpan DeviceTest service.
    device_test: RwLock<Option<DeviceTestProxy>>,
    /// The proxy to access the lowpan DeviceExtra service.
    device_extra: RwLock<Option<DeviceExtraProxy>>,
}

impl WpanFacade {
    pub fn new() -> WpanFacade {
        WpanFacade {
            device: RwLock::new(None),
            device_test: RwLock::new(None),
            device_extra: RwLock::new(None),
        }
    }

    /// Returns the DeviceTestManager proxy provided on instantiation
    /// or establishes a new connection.
    pub async fn initialize_proxies(&self) -> Result<(), Error> {
        let (device, device_extra, device_test) = match LowpanContext::new(None) {
            Ok(low_pan_context) => low_pan_context.get_default_device_proxies().await?,
            _ => bail!("Error retrieving default device proxies"),
        };
        *self.device.write() = Some(device.clone());
        *self.device_extra.write() = Some(device_extra.clone());
        *self.device_test.write() = Some(device_test.clone());
        Ok(())
    }

    /// Returns the thread rloc from the DeviceTest proxy service.
    pub async fn get_thread_rloc16(&self) -> Result<u16, Error> {
        let thread_rloc16 = match self.device_test.read().as_ref() {
            Some(device_test) => device_test.get_thread_rloc16().await?,
            _ => bail!("DeviceTest proxy is not set"),
        };
        Ok(thread_rloc16)
    }

    /// Returns the current mac address (thread random mac address) from the DeviceTest
    /// proxy service.
    pub async fn get_ncp_mac_address(&self) -> Result<[u8; 8], Error> {
        let current_mac_address = match self.device_test.read().as_ref() {
            Some(device_test) => device_test.get_current_mac_address().await?,
            _ => bail!("DeviceTest proxy is not set"),
        };
        Ok(current_mac_address.octets)
    }

    /// Returns the ncp channel from the DeviceTest proxy service.
    pub async fn get_ncp_channel(&self) -> Result<u16, Error> {
        let current_channel = match self.device_test.read().as_ref() {
            Some(device_test) => device_test.get_current_channel().await?,
            _ => bail!("DeviceTest proxy is not set"),
        };
        Ok(current_channel)
    }

    /// Returns the current rssi from the DeviceTest proxy service.
    pub async fn get_ncp_rssi(&self) -> Result<i32, Error> {
        let ncp_rssi = match self.device_test.read().as_ref() {
            Some(device_test) => device_test.get_current_rssi().await?,
            _ => bail!("DeviceTest proxy is not set"),
        };
        Ok(ncp_rssi.into())
    }

    /// Returns the factory mac address from the DeviceTest proxy service.
    pub async fn get_weave_node_id(&self) -> Result<[u8; 8], Error> {
        let factory_mac_address = match self.device_test.read().as_ref() {
            Some(device_test) => device_test.get_factory_mac_address().await?,
            _ => bail!("DeviceTest proxy is not set"),
        };
        Ok(factory_mac_address.octets)
    }

    /// Returns the network name from the DeviceExtra proxy service.
    pub async fn get_network_name(&self) -> Result<Vec<u8>, Error> {
        let raw_name = match self.device_extra.read().as_ref() {
            Some(device_extra) => device_extra.watch_identity().await?.raw_name,
            _ => bail!("DeviceExtra proxy is not set"),
        };
        match raw_name {
            Some(raw_name) => Ok(raw_name),
            None => bail!("Network name is not specified!"),
        }
    }

    /// Returns the partition id from the DeviceTest proxy service.
    pub async fn get_partition_id(&self) -> Result<u32, Error> {
        let partition_id = match self.device_test.read().as_ref() {
            Some(device_test) => device_test.get_partition_id().await?,
            _ => bail!("DeviceTest proxy is not set"),
        };
        Ok(partition_id)
    }

    /// Returns the thread router id from the DeviceTest proxy service.
    pub async fn get_thread_router_id(&self) -> Result<u8, Error> {
        let router_id = match self.device_test.read().as_ref() {
            Some(device_test) => device_test.get_thread_router_id().await?,
            _ => bail!("DeviceTest proxy is not set"),
        };
        Ok(router_id)
    }

    /// Returns the device state from the DeviceTest proxy service.
    pub async fn get_ncp_device_state(&self) -> Result<DeviceStateDto, Error> {
        let device_state = match self.device.read().as_ref() {
            Some(device) => device.watch_device_state().await?,
            _ => bail!("DeviceTest proxy is not set"),
        };
        Ok(device_state.into())
    }

    /// Returns the connectivity state from the DeviceTest proxy service.
    pub async fn get_ncp_state(&self) -> Result<ConnectivityState, Error> {
        let device_state = match self.device.read().as_ref() {
            Some(device) => device.watch_device_state().await?.connectivity_state,
            _ => bail!("DeviceTest proxy is not set"),
        };
        match device_state {
            Some(connectivity_state) => Ok(connectivity_state.into()),
            None => bail!("Device state is not defined!"),
        }
    }

    /// Returns true if the connectivity state is commissioned.
    pub async fn get_is_commissioned(&self) -> Result<bool, Error> {
        let ncp_state = self.get_ncp_state().await?;
        let is_commissioned = match ncp_state {
            ConnectivityState::Attached
            | ConnectivityState::Attaching
            | ConnectivityState::Isolated
            | ConnectivityState::Ready => true,
            _ => false,
        };
        Ok(is_commissioned)
    }

    /// Returns the panid from the DeviceExtra proxy service.
    pub async fn get_panid(&self) -> Result<u16, Error> {
        match self.device_extra.read().as_ref() {
            Some(device_extra) => match device_extra.watch_identity().await?.panid {
                Some(panid) => Ok(panid),
                None => bail!("Pan id is not specified!"),
            },
            _ => bail!("DeviceExtra proxy is not set"),
        }
    }

    /// Returns the mac address filter settings from the DeviceTest proxy service.
    pub async fn get_mac_address_filter_settings(
        &self,
    ) -> Result<MacAddressFilterSettingsDto, Error> {
        let settings = match self.device_test.read().as_ref() {
            Some(device_test) => device_test.get_mac_address_filter_settings().await?,
            _ => bail!("DeviceTest proxy is not set!"),
        };
        Ok(settings.into())
    }

    /// Replaces the mac address filter settings on the DeviceTest proxy service.
    pub async fn replace_mac_address_filter_settings(
        &self,
        settings: MacAddressFilterSettingsDto,
    ) -> Result<(), Error> {
        match self.device_test.read().as_ref() {
            Some(device_test) => {
                device_test.replace_mac_address_filter_settings(&settings.into()).await?
            }
            None => bail!("DeviceTest proxy is not set!"),
        }
        Ok(())
    }

    ///Returns the thread neighbor table from the DeviceTest proxy service.
    pub async fn get_neighbor_table(&self) -> Result<Vec<NeighborInfoDto>, Error> {
        let settings = match self.device_test.read().as_ref() {
            Some(device_test) => device_test.get_neighbor_table().await?,
            _ => bail!("DeviceTest proxy is not set!"),
        };
        Ok(settings.into_iter().map(|setting| setting.into()).collect())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::wpan::types::{MacAddressFilterItemDto, MacAddressFilterModeDto};
    use fidl::endpoints::ProtocolMarker;
    use fidl_fuchsia_lowpan_device::{DeviceExtraMarker, DeviceMarker};
    use fidl_fuchsia_lowpan_test::DeviceTestMarker;
    use fuchsia_async as fasync;
    use futures::prelude::*;
    use lazy_static::lazy_static;
    use lowpan_driver_common::DummyDevice;
    use lowpan_driver_common::ServeTo;

    lazy_static! {
        static ref MOCK_TESTER: MockTester = MockTester::new();
    }

    struct MockTester {
        dummy_device: DummyDevice,
    }
    impl MockTester {
        fn new() -> Self {
            Self { dummy_device: DummyDevice::default() }
        }

        fn create_endpoints<T: ProtocolMarker>() -> (RwLock<Option<T::Proxy>>, T::RequestStream) {
            let (client_ep, server_ep) = fidl::endpoints::create_endpoints::<T>();
            (RwLock::new(Some(client_ep.into_proxy().unwrap())), server_ep.into_stream().unwrap())
        }

        pub fn create_facade_and_serve(
            &'static self,
        ) -> (
            WpanFacade,
            (
                impl Future<Output = anyhow::Result<()>>,
                impl Future<Output = anyhow::Result<()>>,
                impl Future<Output = anyhow::Result<()>>,
            ),
        ) {
            let (device_proxy, device_server) = MockTester::create_endpoints::<DeviceMarker>();
            let (device_test_proxy, device_test_server) =
                MockTester::create_endpoints::<DeviceTestMarker>();
            let (device_extra_proxy, device_extra_server) =
                MockTester::create_endpoints::<DeviceExtraMarker>();

            let facade = WpanFacade {
                device: device_proxy,
                device_test: device_test_proxy,
                device_extra: device_extra_proxy,
            };

            (
                facade,
                (
                    self.dummy_device.serve_to(device_server),
                    self.dummy_device.serve_to(device_test_server),
                    self.dummy_device.serve_to(device_extra_server),
                ),
            )
        }

        pub async fn assert_wpan_fn<TResult>(
            func: impl Future<Output = Result<TResult, Error>>,
            server_future: (
                impl Future<Output = anyhow::Result<()>>,
                impl Future<Output = anyhow::Result<()>>,
                impl Future<Output = anyhow::Result<()>>,
            ),
        ) {
            let facade_fut = async move {
                let awaiting = func.await;
                awaiting.expect("No value returned!");
            };
            futures::select! {
                err = server_future.0.fuse() => panic!("Server task stopped: {:?}", err),
                err = server_future.1.fuse() => panic!("Server task stopped: {:?}", err),
                err = server_future.2.fuse() => panic!("Server task stopped: {:?}", err),
                _ = facade_fut.fuse() => (),
            }
        }
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_thread_rloc16() {
        let facade = MOCK_TESTER.create_facade_and_serve();
        MockTester::assert_wpan_fn(facade.0.get_thread_rloc16(), facade.1).await;
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_ncp_channel() {
        let facade = MOCK_TESTER.create_facade_and_serve();
        MockTester::assert_wpan_fn(facade.0.get_ncp_channel(), facade.1).await;
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_ncp_mac_address() {
        let facade = MOCK_TESTER.create_facade_and_serve();
        MockTester::assert_wpan_fn(facade.0.get_ncp_mac_address(), facade.1).await;
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_ncp_rssi() {
        let facade = MOCK_TESTER.create_facade_and_serve();
        MockTester::assert_wpan_fn(facade.0.get_ncp_rssi(), facade.1).await;
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_weave_node_id() {
        let facade = MOCK_TESTER.create_facade_and_serve();
        MockTester::assert_wpan_fn(facade.0.get_weave_node_id(), facade.1).await;
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_network_name() {
        let facade = MOCK_TESTER.create_facade_and_serve();
        MockTester::assert_wpan_fn(facade.0.get_network_name(), facade.1).await;
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_partition_id() {
        let facade = MOCK_TESTER.create_facade_and_serve();
        MockTester::assert_wpan_fn(facade.0.get_partition_id(), facade.1).await;
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_thread_router_id() {
        let facade = MOCK_TESTER.create_facade_and_serve();
        MockTester::assert_wpan_fn(facade.0.get_thread_router_id(), facade.1).await;
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_ncp_device_state() {
        let facade = MOCK_TESTER.create_facade_and_serve();
        MockTester::assert_wpan_fn(facade.0.get_ncp_device_state(), facade.1).await;
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_ncp_state() {
        let facade = MOCK_TESTER.create_facade_and_serve();
        MockTester::assert_wpan_fn(facade.0.get_ncp_state(), facade.1).await;
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_is_commissioned() {
        let facade = MOCK_TESTER.create_facade_and_serve();
        MockTester::assert_wpan_fn(facade.0.get_is_commissioned(), facade.1).await;
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_panid() {
        let facade = MOCK_TESTER.create_facade_and_serve();
        MockTester::assert_wpan_fn(facade.0.get_panid(), facade.1).await;
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_mac_address_filter_settings() {
        let facade = MOCK_TESTER.create_facade_and_serve();
        MockTester::assert_wpan_fn(facade.0.get_mac_address_filter_settings(), facade.1).await;
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_replace_mac_address_filter_settings() {
        let facade = MOCK_TESTER.create_facade_and_serve();
        MockTester::assert_wpan_fn(
            facade.0.replace_mac_address_filter_settings(MacAddressFilterSettingsDto {
                mode: Some(MacAddressFilterModeDto::Allow),
                items: Some(vec![MacAddressFilterItemDto {
                    mac_address: Some([0, 1, 2, 3, 4, 5, 6, 7]),
                    rssi: None,
                }]),
            }),
            facade.1,
        )
        .await;
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_neigbor_table() {
        let facade = MOCK_TESTER.create_facade_and_serve();
        MockTester::assert_wpan_fn(facade.0.get_neighbor_table(), facade.1).await;
    }
}
