// 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::common_utils::common::LazyProxy;
use crate::weave::types::{PairingState, ResetConfig};
use anyhow::Error;
use fidl::endpoints::create_proxy;
use fidl_fuchsia_weave::{
    ErrorCode, FactoryDataManagerMarker, FactoryDataManagerProxy, PairingStateWatcherMarker,
    PairingStateWatcherProxy, ResetConfigFlags, StackMarker, StackProxy,
};
use serde_json::Value;

/// Perform Weave FIDL operations.
///
/// Note this object is shared among all threads created by server.
#[derive(Debug)]
pub struct WeaveFacade {
    factory_data_manager: LazyProxy<FactoryDataManagerMarker>,
    stack: LazyProxy<StackMarker>,
}

impl WeaveFacade {
    pub fn new() -> WeaveFacade {
        WeaveFacade { factory_data_manager: Default::default(), stack: Default::default() }
    }

    /// Returns the FactoryDataManager proxy provided on instantiation
    /// or establishes a new connection.
    fn factory_data_manager(&self) -> Result<FactoryDataManagerProxy, Error> {
        self.factory_data_manager.get_or_connect()
    }

    /// Returns the Stack proxy provided on instantiation or establishes a new connection.
    fn stack(&self) -> Result<StackProxy, Error> {
        self.stack.get_or_connect()
    }

    /// Returns the PairingStateWatcher proxy provided on instantiation.
    fn pairing_state_watcher(&self) -> Result<PairingStateWatcherProxy, Error> {
        let (pairing_proxy, pairing_server_end) = create_proxy::<PairingStateWatcherMarker>()?;
        self.stack()?.get_pairing_state_watcher(pairing_server_end)?;
        Ok(pairing_proxy)
    }

    /// Returns a string mapped from the provided Weave error code.
    fn map_weave_err(&self, code: ErrorCode) -> anyhow::Error {
        anyhow!(match code {
            ErrorCode::FileNotFound => "FileNotFound",
            ErrorCode::CryptoError => "CryptoError",
            ErrorCode::InvalidArgument => "InvalidArgument",
            ErrorCode::InvalidState => "InvalidState",
            ErrorCode::UnspecifiedError => "UnspecifiedError",
        })
    }

    /// Returns the pairing code from the FactoryDataManager proxy service.
    pub async fn get_pairing_code(&self) -> Result<Vec<u8>, Error> {
        self.factory_data_manager()?.get_pairing_code().await?.map_err(|e| self.map_weave_err(e))
    }

    /// Returns the qr code from the StackManager proxy service.
    pub async fn get_qr_code(&self) -> Result<String, Error> {
        self.stack()?
            .get_qr_code()
            .await?
            .map(|qr_code| qr_code.data)
            .map_err(|e| self.map_weave_err(e))
    }

    /// Returns the pairing state from the PairingStateWatcher service.
    pub async fn get_pairing_state(&self) -> Result<PairingState, Error> {
        let watch = self.pairing_state_watcher()?.watch_pairing_state().await;
        watch.map(|pairing_state| pairing_state.into()).map_err(anyhow::Error::from)
    }

    /// Resets Weave state by wiping the provided configurations.
    ///
    /// # Arguments
    /// * `args`: The JSON indicating the configurations to reset, in the form of a list of bytes.
    ///
    /// # JSON Format
    /// All fields are optional. Fields set to 'true' reset the corresponding configuration in
    /// weave, and fields left unset default to 'false'.
    ///
    /// {
    ///   network_config: true,
    ///   fabric_config: false,
    ///   service_config: true,
    ///   operational_credentials: false
    /// }
    pub async fn reset_config(&self, args: Value) -> Result<(), Error> {
        let flags: ResetConfig = serde_json::from_value(args)?;
        self.stack()?
            .reset_config(ResetConfigFlags::from(flags))
            .await?
            .map_err(|e| self.map_weave_err(e))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use assert_matches::assert_matches;
    use fidl::endpoints::create_proxy_and_stream;
    use fidl_fuchsia_weave::{
        FactoryDataManagerRequest, PairingStateWatcherRequest, QrCode, StackGetQrCodeResult,
        StackRequest, StackResetConfigResult,
    };
    use fuchsia_async as fasync;
    use futures::prelude::*;
    use lazy_static::lazy_static;
    use serde_json::json;

    const PAIRING_CODE: &'static [u8] = b"ABC1234";

    lazy_static! {
        static ref QR_CODE: QrCode = QrCode { data: String::from("qrcodedata") };
        static ref PAIRING_STATE: PairingState = PairingState {
            is_wlan_provisioned: Some(true),
            is_fabric_provisioned: Some(true),
            is_service_provisioned: Some(false),
            is_weave_fully_provisioned: Some(false),
            is_thread_provisioned: Some(true)
        };
        static ref RESET_CONFIG: Value = json!({
            "network_config": true,
            // "fabric_config" unset
            "service_config": true,
            // "operational_credentials" unset
        });
    }

    struct MockStackBuilder {
        expected_stack: Vec<Box<dyn FnOnce(StackRequest) + Send + 'static>>,
        expected_pair: Vec<Box<dyn FnOnce(PairingStateWatcherRequest) + Send + 'static>>,
    }

    impl MockStackBuilder {
        fn new() -> Self {
            Self { expected_stack: vec![], expected_pair: vec![] }
        }

        fn push_stack(mut self, request: impl FnOnce(StackRequest) + Send + 'static) -> Self {
            self.expected_stack.push(Box::new(request));
            self
        }

        fn push_pair(
            mut self,
            request: impl FnOnce(PairingStateWatcherRequest) + Send + 'static,
        ) -> Self {
            self.expected_pair.push(Box::new(request));
            self
        }

        fn expect_get_qr_code(self, result: StackGetQrCodeResult) -> Self {
            self.push_stack(move |req| match req {
                StackRequest::GetQrCode { responder } => {
                    responder.send(result.as_ref().map_err(|e| *e)).unwrap()
                }
                req => panic!("unexpected request: {:?}", req),
            })
        }

        fn expect_get_pairing_state(self, result: PairingState) -> Self {
            self.push_pair(move |req| match req {
                PairingStateWatcherRequest::WatchPairingState { responder } => {
                    responder.send(&fidl_fuchsia_weave::PairingState::from(result)).unwrap();
                }
            })
        }

        fn expect_reset_config(
            self,
            _expected_flags: fidl_fuchsia_weave::ResetConfigFlags,
            result: StackResetConfigResult,
        ) -> Self {
            self.push_stack(move |req| match req {
                StackRequest::ResetConfig { responder, flags } => {
                    assert_matches!(flags, _expected_flags);
                    responder.send(result).unwrap()
                }
                req => panic!("unexpected request: {:?}", req),
            })
        }

        fn build_stack(self) -> (WeaveFacade, impl Future<Output = ()>) {
            let (proxy, mut stream) = create_proxy_and_stream::<StackMarker>().unwrap();
            let fut = async move {
                let _ = &self;
                for expected in self.expected_stack {
                    expected(stream.next().await.unwrap().unwrap());
                }
                assert_matches!(stream.next().await, None);
            };
            let facade = WeaveFacade::new();
            facade.stack.set(proxy).expect("just-created facade should have empty stack");
            (facade, fut)
        }
        fn build_stack_and_pairing_state_watcher(self) -> (WeaveFacade, impl Future<Output = ()>) {
            let (proxy, mut stream) = create_proxy_and_stream::<StackMarker>().unwrap();
            let stream_fut = async move {
                let _ = &self;
                match stream.next().await {
                    Some(Ok(StackRequest::GetPairingStateWatcher {
                        watcher,
                        control_handle: _,
                    })) => {
                        let mut into_stream = watcher.into_stream().unwrap();
                        for expected in self.expected_pair {
                            expected(into_stream.next().await.unwrap().unwrap());
                        }
                        assert_matches!(into_stream.next().await, None);
                    }
                    err => panic!("Error in request handler: {:?}", err),
                }
            };
            let facade = WeaveFacade::new();
            facade.stack.set(proxy).expect("just-created facade should have empty stack");
            (facade, stream_fut)
        }
    }

    struct MockFactoryDataManagerBuilder {
        expected: Vec<Box<dyn FnOnce(FactoryDataManagerRequest) + Send + 'static>>,
    }

    impl MockFactoryDataManagerBuilder {
        fn new() -> Self {
            Self { expected: vec![] }
        }

        fn push(
            mut self,
            request: impl FnOnce(FactoryDataManagerRequest) + Send + 'static,
        ) -> Self {
            self.expected.push(Box::new(request));
            self
        }

        fn expect_get_pairing_code(self, result: Result<&'static [u8], ErrorCode>) -> Self {
            self.push(move |req| match req {
                FactoryDataManagerRequest::GetPairingCode { responder } => {
                    responder.send(result).unwrap()
                }
                _ => {}
            })
        }

        fn build(self) -> (WeaveFacade, impl Future<Output = ()>) {
            let (proxy, mut stream) =
                fidl::endpoints::create_proxy_and_stream::<FactoryDataManagerMarker>().unwrap();
            let fut = async move {
                for expected in self.expected {
                    expected(stream.next().await.unwrap().unwrap());
                }
                assert_matches!(stream.next().await, None);
            };
            let facade = WeaveFacade::new();
            facade
                .factory_data_manager
                .set(proxy)
                .expect("just-created facade should have empty fdm");
            (facade, fut)
        }
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_pairing_code() {
        let (facade, pairing_code_fut) =
            MockFactoryDataManagerBuilder::new().expect_get_pairing_code(Ok(PAIRING_CODE)).build();

        let facade_fut = async move {
            assert_eq!(facade.get_pairing_code().await.unwrap(), PAIRING_CODE);
        };

        future::join(facade_fut, pairing_code_fut).await;
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_qr_code() {
        let qr_clone: StackGetQrCodeResult = Ok((*QR_CODE).clone());
        let (facade, qr_code_fut) =
            MockStackBuilder::new().expect_get_qr_code(qr_clone).build_stack();

        let facade_fut = async move {
            assert_eq!(facade.get_qr_code().await.unwrap(), *QR_CODE.data);
        };

        future::join(facade_fut, qr_code_fut).await;
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_pairing_state() {
        let (facade, pairing_state_fut) = MockStackBuilder::new()
            .expect_get_pairing_state(*PAIRING_STATE)
            .build_stack_and_pairing_state_watcher();

        let facade_fut = async move {
            let pairing_state = facade.get_pairing_state().await.unwrap();
            assert_eq!(pairing_state, *PAIRING_STATE);
        };

        future::join(facade_fut, pairing_state_fut).await;
    }

    #[allow(clippy::unit_cmp)] // TODO(https://fxbug.dev/42176996)
    #[fasync::run_singlethreaded(test)]
    async fn test_reset_config() {
        let flags: ResetConfigFlags = fidl_fuchsia_weave::ResetConfigFlags::NETWORK_CONFIG
            | fidl_fuchsia_weave::ResetConfigFlags::SERVICE_CONFIG;
        let (facade, reset_config_fut) =
            MockStackBuilder::new().expect_reset_config(flags, Ok(())).build_stack();

        let facade_fut =
            async move { assert_eq!(facade.reset_config(RESET_CONFIG.clone()).await.unwrap(), ()) };

        future::join(facade_fut, reset_config_fut).await;
    }
}
