// Copyright 2018 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 {
    failure::Error,
    fidl::endpoints::create_proxy,
    fidl_fuchsia_bluetooth_host::BondingData,
    fidl_fuchsia_stash::{
        GetIteratorMarker,
        StoreAccessorMarker,
        StoreAccessorProxy,
        StoreMarker,
        Value,
    },
    fuchsia_bluetooth::error::Error as BtError,
    fuchsia_syslog::{fx_log_info, fx_log_err},
    serde_json,
    std::collections::HashMap,
};

use crate::store::{
    keys::{BONDING_DATA_PREFIX, bonding_data_key},
    serde::{ BondingDataDeserializer, BondingDataSerializer},
};

/// Stash manages persistent data that is stored in bt-gap's component-specific storage.
#[derive(Debug)]
pub struct Stash {
    // The proxy to the Fuchsia stash service. This is assumed to have been initialized as a
    // read/write capable accessor with the identity of the current component.
    proxy: StoreAccessorProxy,

    // In-memory state of the bonding data stash. Each entry is hierarchically indexed by a
    // local Bluetooth adapter identity and a peer device identifier.
    bonding_data: HashMap<String, HashMap<String, BondingData>>,
}

impl Stash {
    /// Updates the bonding data for a given device. Creates a new entry if one matching this
    /// device does not exist.
    pub fn store_bond(&mut self, data: BondingData) -> Result<(), Error> {
        fx_log_info!("store_bond (id: {})", data.identifier);

        // Persist the serialized blob.
        let serialized = serde_json::to_string(&BondingDataSerializer(&data))?;
        self.proxy.set_value(
            &bonding_data_key(&data.identifier),
            &mut Value::Stringval(serialized),
        )?;
        self.proxy.commit()?;

        // Update the in memory cache.
        let local_map = self
            .bonding_data
            .entry(data.local_address.clone())
            .or_insert(HashMap::new());
        local_map.insert(data.identifier.clone(), data);
        Ok(())
    }

    /// Returns an iterator over the bonding data entries for the local adapter with the given
    /// `address`. Returns None if no such data exists.
    pub fn list_bonds(&self, local_address: &str) -> Option<impl Iterator<Item = &BondingData>> {
        Some(self.bonding_data.get(local_address)?.values().into_iter())
    }

    // Initializes the stash using the given `accessor`. This asynchronously loads existing
    // stash data. Returns an error in case of failure.
    async fn new(accessor: StoreAccessorProxy) -> Result<Stash, Error> {
        // Obtain a list iterator for all cached bonding data.
        let (iter, server_end) = create_proxy::<GetIteratorMarker>()?;
        accessor.get_prefix(BONDING_DATA_PREFIX, server_end)?;

        let mut bonding_map = HashMap::new();
        loop {
            let next = await!(iter.get_next())?;
            if next.is_empty() {
                break;
            }
            for key_value in next {
                if let Value::Stringval(json) = key_value.val {
                    let bonding_data: BondingDataDeserializer = serde_json::from_str(&json)?;
                    let bonding_data = bonding_data.contents();
                    let local_address_entries = bonding_map
                        .entry(bonding_data.local_address.clone())
                        .or_insert(HashMap::new());
                    local_address_entries.insert(bonding_data.identifier.clone(), bonding_data);
                } else {
                    fx_log_err!("stash malformed: bonding data should be a string");
                    return Err(BtError::new("failed to initialize stash").into());
                }
            }
        }
        Ok(Stash {
            proxy: accessor,
            bonding_data: bonding_map,
        })
    }
}

/// Connects to the stash service and initializes a Stash object. This function obtains
/// read/write capability to the component-specific storage identified by `component_id`.
pub async fn init_stash(component_id: &str) -> Result<Stash, Error> {
    let stash_svc = fuchsia_app::client::connect_to_service::<StoreMarker>()?;
    stash_svc.identify(component_id)?;

    let (proxy, server_end) = create_proxy::<StoreAccessorMarker>()?;
    stash_svc.create_accessor(false, server_end)?;

    await!(Stash::new(proxy))
}

// These tests access stash in a hermetic envionment and thus it's ok for state to leak between
// test runs, regardless of test failure. Each test clears out the state in stash before performing
// its test logic.
#[cfg(test)]
mod tests {
    use super::*;
    use {fuchsia_app::client::connect_to_service,
         fuchsia_async as fasync,
         pin_utils::pin_mut};

    // create_stash_accessor will create a new accessor to stash scoped under the given test name.
    // All preexisting data in stash under this identity is deleted before the accessor is
    // returned.
    fn create_stash_accessor(test_name: &str) -> Result<StoreAccessorProxy, Error> {
        let stashserver = connect_to_service::<StoreMarker>()?;

        // Identify
        stashserver.identify(&(BONDING_DATA_PREFIX.to_owned() + test_name))?;

        // Create an accessor
        let (acc, server_end) = create_proxy()?;
        stashserver.create_accessor(false, server_end)?;

        // Clear all data in stash under our identity
        acc.delete_prefix("")?;
        acc.commit()?;

        Ok(acc)
    }

    #[test]
    fn new_stash_succeeds_with_empty_values() {
        let mut exec = fasync::Executor::new().expect("failed to create an executor");

        // Create a Stash service interface.
        let accessor_proxy = create_stash_accessor("new_stash_succeeds_with_empty_values")
                    .expect("failed to create StashAccessor");
        let stash_new_future = Stash::new(accessor_proxy);
        pin_mut!(stash_new_future);

        // The stash should be initialized with no data.
        assert!(exec.run_singlethreaded(stash_new_future)
                    .expect("expected Stash to initialize")
                    .bonding_data.is_empty());
    }

    #[test]
    fn new_stash_fails_with_malformed_key_value_entry() {
        let mut exec = fasync::Executor::new().expect("failed to create an executor");

        // Create a Stash service interface.
        let accessor_proxy =
                create_stash_accessor("new_stash_fails_with_malformed_key_value_entry")
                    .expect("failed to create StashAccessor");

        // Set a key/value that contains a non-string value.
        accessor_proxy.set_value("bonding-data:test1234", &mut Value::Intval(5))
            .expect("failed to set a bonding data value");
        accessor_proxy.commit()
            .expect("failed to commit a bonding data value");

        // The stash should fail to initialize.
        let stash_new_future = Stash::new(accessor_proxy);
        assert!(exec.run_singlethreaded(stash_new_future).is_err());
    }

    #[test]
    fn new_stash_fails_with_malformed_json() {
        let mut exec = fasync::Executor::new().expect("failed to create an executor");

        // Create a mock Stash service interface.
        let accessor_proxy = create_stash_accessor("new_stash_fails_with_malformed_json")
                    .expect("failed to create StashAccessor");

        // Set a vector that contains a malformed JSON value
        accessor_proxy.set_value("bonding-data:test1234", &mut Value::Stringval("{0}".to_string()))
            .expect("failed to set a bonding data value");
        accessor_proxy.commit()
            .expect("failed to commit a bonding data value");

        // The stash should fail to initialize.
        let stash_new_future = Stash::new(accessor_proxy);
        assert!(exec.run_singlethreaded(stash_new_future).is_err());
    }

    #[test]
    fn new_stash_succeeds_with_values() {
        let mut exec = fasync::Executor::new().expect("failed to create an executor");

        // Create a Stash service interface.
        let accessor_proxy = create_stash_accessor("new_stash_succeeds_with_values")
                    .expect("failed to create StashAccessor");


        // Insert values into stash that contain bonding data for several devices.
        accessor_proxy.set_value("bonding-data:id-1", &mut Value::Stringval(
                    r#"
                    {
                       "identifier": "id-1",
                       "localAddress": "00:00:00:00:00:01",
                       "name": "Test Device 1",
                       "le": null
                    }"#
                    .to_string(),
                )).expect("failed to set value");
        accessor_proxy.set_value("bonding-data:id-2", &mut Value::Stringval(
                    r#"
                    {
                       "identifier": "id-2",
                       "localAddress": "00:00:00:00:00:01",
                       "name": "Test Device 2",
                       "le": null
                    }"#
                    .to_string(),
                )).expect("failed to set value");
        accessor_proxy.set_value("bonding-data:id-3", &mut Value::Stringval(
                    r#"
                    {
                       "identifier": "id-3",
                       "localAddress": "00:00:00:00:00:02",
                       "name": null,
                       "le": null
                    }"#
                    .to_string(),
                )).expect("failed to set value");
        accessor_proxy.commit()
            .expect("failed to commit bonding data values");

        // The stash should initialize with bonding data stored in stash
        let stash_new_future = Stash::new(accessor_proxy);
        let stash = exec.run_singlethreaded(stash_new_future).expect("stash failed to initialize");

        // There should be devices registered for two local addresses.
        assert_eq!(2, stash.bonding_data.len());

        // The first local address should have two devices associated with it.
        let local = stash
            .bonding_data
            .get("00:00:00:00:00:01")
            .expect("could not find local address entries");
        assert_eq!(2, local.len());
        assert_eq!(
            &BondingData {
                identifier: "id-1".to_string(),
                local_address: "00:00:00:00:00:01".to_string(),
                name: Some("Test Device 1".to_string()),
                le: None,
            },
            local.get("id-1").expect("could not find device")
        );
        assert_eq!(
            &BondingData {
                identifier: "id-2".to_string(),
                local_address: "00:00:00:00:00:01".to_string(),
                name: Some("Test Device 2".to_string()),
                le: None,
            },
            local.get("id-2").expect("could not find device")
        );

        // The second local address should have one device associated with it.
        let local = stash
            .bonding_data
            .get("00:00:00:00:00:02")
            .expect("could not find local address entries");
        assert_eq!(1, local.len());
        assert_eq!(
            &BondingData {
                identifier: "id-3".to_string(),
                local_address: "00:00:00:00:00:02".to_string(),
                name: None,
                le: None,
            },
            local.get("id-3").expect("could not find device")
        );
    }

    #[test]
    fn store_bond_commits_entry() {
        let mut exec = fasync::Executor::new().expect("failed to create an executor");
        let accessor_proxy = create_stash_accessor("store_bond_commits_entry")
                    .expect("failed to create StashAccessor");
        let mut stash = exec.run_singlethreaded(Stash::new(accessor_proxy.clone()))
            .expect("stash failed to initialize");

        let bonding_data = BondingData {
            identifier: "id-1".to_string(),
            local_address: "00:00:00:00:00:01".to_string(),
            name: None,
            le: None,
        };
        assert!(stash.store_bond(bonding_data).is_ok());

        // Make sure that the in-memory cache has been updated.
        assert_eq!(1, stash.bonding_data.len());
        assert_eq!(
            &BondingData {
                identifier: "id-1".to_string(),
                local_address: "00:00:00:00:00:01".to_string(),
                name: None,
                le: None,
            },
            stash
                .bonding_data
                .get("00:00:00:00:00:01")
                .unwrap()
                .get("id-1")
                .unwrap()
        );

        // The new data should be accessible over FIDL.
        assert_eq!(exec.run_singlethreaded(accessor_proxy.get_value("bonding-data:id-1"))
                       .expect("failed to get value")
                       .map(|x| *x),
            Some(Value::Stringval(
                "{\"identifier\":\"id-1\",\"localAddress\":\"00:00:00:00:00:01\",\"name\":null,\
                 \"le\":null}"
                    .to_string()
            )));
    }

    #[test]
    fn list_bonds() {
        let mut exec = fasync::Executor::new().expect("failed to create an executor");
        let accessor_proxy = create_stash_accessor("list_bonds")
                    .expect("failed to create StashAccessor");

        // Insert values into stash that contain bonding data for several devices.
        accessor_proxy.set_value("bonding-data:id-1", &mut Value::Stringval(
                    r#"
                    {
                       "identifier": "id-1",
                       "localAddress": "00:00:00:00:00:01",
                       "name": null,
                       "le": null
                    }"#
                    .to_string(),
                )).expect("failed to set value");
        accessor_proxy.set_value("bonding-data:id-2", &mut Value::Stringval(
                    r#"
                    {
                       "identifier": "id-2",
                       "localAddress": "00:00:00:00:00:01",
                       "name": null,
                       "le": null
                    }"#
                    .to_string(),
                )).expect("failed to set value");
        accessor_proxy.commit()
            .expect("failed to commit bonding data values");

        let stash = exec.run_singlethreaded(Stash::new(accessor_proxy))
            .expect("stash failed to initialize");

        // Should return None for unknown address.
        assert!(stash.list_bonds("00:00:00:00:00:00").is_none());

        let mut iter = stash
            .list_bonds("00:00:00:00:00:01")
            .expect("expected to find address");
        let next_id = &iter.next().unwrap().identifier;
        assert!("id-1" == next_id.as_str() || "id-2" == next_id.as_str());
        let next_id = &iter.next().unwrap().identifier;
        assert!("id-1" == next_id.as_str() || "id-2" == next_id.as_str());
        assert_eq!(None, iter.next());
    }
}
