// 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.

//! The store can be serialized and deserialized as a custom form of tlv:
//! https://en.wikipedia.org/wiki/Type-length-value
//!
//! It would be simpler here to simply pull in an external library to do something like json
//! serialization, but this implementation is much less likely to cause security concerns due to the
//! reduced functionality of the code.

use anyhow::{format_err, Context, Error};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use fidl_fuchsia_mem;
use fidl_fuchsia_stash::{KeyValue, ListItem, Value, ValueType};
use fuchsia_zircon as zx;
use std::collections::HashMap;
use std::fs;
use std::io::{Cursor, ErrorKind, Read, Write};
use std::path::PathBuf;
use tracing::info;

pub type ClientName = String;
pub type Key = String;

/// Clones a Value reference into a new Value. Can fail if the syscalls to clone a vmo fail.
/// We need to be able to clone Value to use it directly in the store, but both the Clone trait and
/// Value struct are external, so we can't impl Clone for Value.
pub fn clone_value(v: &Value) -> Result<Value, Error> {
    Ok(match v {
        Value::Intval(x) => Value::Intval(x.clone()),
        Value::Floatval(x) => Value::Floatval(x.clone()),
        Value::Boolval(x) => Value::Boolval(x.clone()),
        Value::Stringval(x) => Value::Stringval(x.clone()),
        Value::Bytesval(x) => Value::Bytesval(clone_buffer(x)?),
    })
}

/// Creates a copy-on-write clone of the given fidl buffer
pub fn clone_buffer(b: &fidl_fuchsia_mem::Buffer) -> Result<fidl_fuchsia_mem::Buffer, Error> {
    let new_vmo = b
        .vmo
        .create_child(zx::VmoChildOptions::SNAPSHOT_AT_LEAST_ON_WRITE, 0, b.size)
        .map_err(|s| format_err!(format!("error cloning buffer, zx status: {}", s)))?;
    Ok(fidl_fuchsia_mem::Buffer { vmo: new_vmo, size: b.size })
}

/// Store is the struct representing the contents of the backing tlv file
#[derive(Debug, PartialEq, Default)]
pub struct Store {
    data: HashMap<ClientName, HashMap<Key, Value>>,
}

fn value_type_as_bytes(v: &Value) -> &[u8] {
    match v {
        Value::Intval(_) => &[0x00],
        Value::Floatval(_) => &[0x01],
        Value::Boolval(_) => &[0x02],
        Value::Stringval(_) => &[0x03],
        Value::Bytesval(_) => &[0x04],
    }
}

fn value_into_bytes(v: &Value) -> Result<Vec<u8>, Error> {
    let mut wrt = vec![];
    match v {
        Value::Intval(i) => wrt.write_i64::<LittleEndian>(*i)?,
        Value::Floatval(f) => wrt.write_f64::<LittleEndian>(*f)?,
        Value::Boolval(false) => wrt.write_u8(0x00)?,
        Value::Boolval(true) => wrt.write_u8(0x01)?,
        Value::Stringval(s) => wrt.append(&mut s.clone().into_bytes()),
        Value::Bytesval(b) => {
            let mut buf = vec![0; b.size as usize];
            b.vmo
                .read(&mut buf, 0)
                .map_err(|s| format_err!(format!("error reading buffer, zx status: {}", s)))?;
            wrt.append(&mut buf);
        }
    }
    Ok(wrt)
}
fn value_from_bytes(typ: u8, bytes: Vec<u8>) -> Result<Value, Error> {
    match typ {
        0x00 => Ok(Value::Intval(Cursor::new(bytes).read_i64::<LittleEndian>()?)),
        0x01 => Ok(Value::Floatval(Cursor::new(bytes).read_f64::<LittleEndian>()?)),
        0x02 => match Cursor::new(bytes).read_u8()? {
            0x00 => Ok(Value::Boolval(false)),
            0x01 => Ok(Value::Boolval(true)),
            b => Err(format_err!(format!("unknown bool value: {}", b))),
        },
        0x03 => Ok(Value::Stringval(String::from_utf8(bytes)?)),
        0x04 => {
            let vmo = zx::Vmo::create(bytes.len() as u64)
                .map_err(|s| format_err!(format!("error creating buffer, zx status: {}", s)))?;
            vmo.write(&bytes, 0)
                .map_err(|s| format_err!(format!("error writing buffer, zx status: {}", s)))?;
            Ok(Value::Bytesval(fidl_fuchsia_mem::Buffer { vmo: vmo, size: bytes.len() as u64 }))
        }
        t => Err(format_err!(format!("unknown type: {}", t))),
    }
}

impl Store {
    fn serialize(&self) -> Result<Vec<u8>, Error> {
        let mut res = vec![];
        for (client_name, client_data) in self.data.iter() {
            let mut client_name_length = vec![];
            client_name_length.write_u64::<LittleEndian>(client_name.len() as u64)?;
            let mut client_name_bytes = client_name.clone().into_bytes();

            let mut client_entries = vec![];
            client_entries.write_u64::<LittleEndian>(client_data.len() as u64)?;

            res.append(&mut client_name_length);
            res.append(&mut client_name_bytes);
            res.append(&mut client_entries);

            for (key, val) in client_data {
                let mut key_length = vec![];
                key_length.write_u64::<LittleEndian>(key.len() as u64)?;
                let mut key_bytes = key.clone().into_bytes();
                let val_type = value_type_as_bytes(val);
                let mut val_bytes = value_into_bytes(val)?;
                let mut val_length = vec![];
                val_length.write_u64::<LittleEndian>(val_bytes.len() as u64)?;

                res.append(&mut key_length);
                res.append(&mut key_bytes);
                res.extend_from_slice(val_type);
                res.append(&mut val_length);
                res.append(&mut val_bytes);
            }
        }
        Ok(res)
    }

    fn deserialize(bytes: Vec<u8>) -> Result<Store, Error> {
        let mut res = Store::default();
        let bytes_len = bytes.len();
        let mut cursor = Cursor::new(bytes);
        while cursor.position() < bytes_len as u64 {
            let client_name_length =
                cursor.read_u64::<LittleEndian>().context("reading name length")? as usize;
            let mut client_name = Vec::new();
            client_name.resize(client_name_length, 0);
            cursor.read_exact(&mut client_name[..]).context("reading name")?;

            let client_entries = cursor.read_u64::<LittleEndian>().context("reading # entries")?;

            let mut client_data = HashMap::new();
            for _ in 0..client_entries {
                let key_length =
                    cursor.read_u64::<LittleEndian>().context("reading key length")? as usize;
                let mut key_bytes = Vec::new();
                key_bytes.resize(key_length, 0);
                cursor.read_exact(&mut key_bytes[..]).context("reading key")?;

                let mut val_type = [0; 1];
                cursor.read_exact(&mut val_type[..]).context("reading value type")?;
                let val_type = val_type[0];

                let val_length =
                    cursor.read_u64::<LittleEndian>().context("reading value length")? as usize;

                let mut val_bytes = Vec::new();
                val_bytes.resize(val_length, 0);
                cursor.read_exact(&mut val_bytes[..]).context("reading value")?;

                client_data
                    .insert(String::from_utf8(key_bytes)?, value_from_bytes(val_type, val_bytes)?);
            }

            res.data.insert(String::from_utf8(client_name)?, client_data);
        }
        Ok(res)
    }
}

pub fn value_to_type(v: &Value) -> ValueType {
    match v {
        Value::Intval(_) => ValueType::IntVal,
        Value::Floatval(_) => ValueType::FloatVal,
        Value::Boolval(_) => ValueType::BoolVal,
        Value::Stringval(_) => ValueType::StringVal,
        Value::Bytesval(_) => ValueType::BytesVal,
    }
}

/// StoreManager is used to hold and manipulate a Store, writing changes to disk when appropriate.
pub struct StoreManager {
    backing_file: PathBuf,
    store: Store,
}

impl StoreManager {
    /// Create a new StoreManager, loading the store from backing_file if it exists, and writing
    /// changes to the store into backing_file.
    pub fn new<P: Into<PathBuf>>(backing_file: P) -> Result<StoreManager, Error> {
        let backing_file = backing_file.into();
        let store = match fs::read(&backing_file) {
            Ok(buf) => Store::deserialize(buf)?,
            Err(e) => {
                if e.kind() != ErrorKind::NotFound {
                    return Err(format_err!(format!("{}", e)));
                }
                info!("store file doesn't exist, using empty store");
                Store::default()
            }
        };

        Ok(StoreManager { backing_file, store })
    }

    fn save_store(&self) -> Result<(), Error> {
        let temp_file_path = self.backing_file.with_extension("tmp");
        let store_contents = self.store.serialize()?;
        {
            let mut f = fs::OpenOptions::new()
                .write(true)
                .truncate(true)
                .create(true)
                .open(temp_file_path.clone())?;

            f.write_all(&store_contents)?;
        }
        fs::rename(temp_file_path, &self.backing_file)?;
        Ok(())
    }

    /// Gets a value from the store. Returns None if the value is unset.
    pub fn get_value(&self, client_name: &str, key: &str) -> Option<&Value> {
        match self.store.data.get(client_name) {
            None => None,
            Some(client_fields) => client_fields.get(key),
        }
    }

    /// Sets a value in the store.
    pub fn set_value(&mut self, client_name: &str, key: String, field: Value) -> Result<(), Error> {
        let client_fields =
            self.store.data.entry(client_name.to_string()).or_insert(HashMap::new());
        client_fields.insert(key, field);
        self.save_store()
    }

    /// Delete a value from the store. Will return Ok(true) for a successful deletion, Ok(false) if
    /// the field doesn't exist, and Err(e) on any unexpected errors.
    pub fn delete_value(&mut self, client_name: &str, key: &str) -> Result<(), Error> {
        let client_fields =
            self.store.data.entry(client_name.to_string()).or_insert(HashMap::new());
        client_fields.remove(key);
        self.save_store()
    }

    /// Retrieves a list of key/type pairs for all keys containing the given prefix.
    pub fn list_prefix(&self, client_name: &str, prefix: &str) -> Vec<ListItem> {
        let o_client_fields = self.store.data.get(client_name);
        if o_client_fields.is_none() {
            return vec![];
        }
        let client_fields = o_client_fields.unwrap();
        let mut result = vec![];
        for (k, v) in client_fields.iter() {
            if k.starts_with(prefix) {
                result.push(ListItem { key: k.clone(), type_: value_to_type(&v) });
            }
        }
        result
    }

    /// Retrieves a list of key/value pairs for all keys containing the given prefix.
    pub fn get_prefix(&self, client_name: &str, prefix: &str) -> Result<Vec<KeyValue>, Error> {
        let o_client_fields = self.store.data.get(client_name);
        if o_client_fields.is_none() {
            return Ok(vec![]);
        }
        let client_fields = o_client_fields.unwrap();
        let mut res = Vec::new();
        for (k, v) in client_fields.iter() {
            if k.starts_with(prefix) {
                res.push(KeyValue { key: k.clone(), val: clone_value(v)? });
            }
        }
        Ok(res)
    }
}

#[cfg(test)]
mod tests {
    use crate::store::*;
    use std::io;
    use tempfile::TempDir;

    fn get_tmp_store_manager(tmp_dir: &TempDir) -> StoreManager {
        StoreManager::new(tmp_dir.path().join("stash.store")).unwrap()
    }

    /// Store the data supplied. Return the bytes of the store file.
    fn write_tmp_store(id: &str, values: HashMap<String, Value>) -> Result<Vec<u8>, Error> {
        let tmp_dir = TempDir::new().unwrap();
        let mut sm = get_tmp_store_manager(&tmp_dir);

        let test_client_name = id.to_string();

        sm.store.data.insert(test_client_name.clone(), values);
        sm.store.serialize()
    }

    #[test]
    fn test_get_value() {
        let tmp_dir = TempDir::new().unwrap();
        let mut sm = get_tmp_store_manager(&tmp_dir);

        let test_client_name = "test_client".to_owned();
        let test_key = "test_key".to_owned();
        let test_field = Value::Boolval(true);

        let mut client_data = HashMap::new();
        client_data.insert(test_key.clone(), clone_value(&test_field).unwrap());

        sm.store.data.insert(test_client_name.clone(), client_data);
        sm.save_store().unwrap();

        let fetched_field = sm.get_value(&test_client_name, &test_key);
        assert_eq!(fetched_field, Some(&test_field));
    }

    #[test]
    fn test_get_nonexistent_value() {
        let tmp_dir = TempDir::new().unwrap();
        let sm = get_tmp_store_manager(&tmp_dir);

        let test_client_name = "test_client".to_owned();
        let test_key = "test_key".to_owned();

        let fetched_field = sm.get_value(&test_client_name, &test_key);
        assert_eq!(fetched_field, None);
    }

    #[test]
    fn test_set_value() {
        let tmp_dir = TempDir::new().unwrap();
        let mut sm = get_tmp_store_manager(&tmp_dir);

        let test_client_name = "test_client".to_owned();
        let test_key = "test_key".to_owned();
        let test_field = Value::Boolval(true);

        sm.set_value(&test_client_name, test_key.clone(), clone_value(&test_field).unwrap())
            .unwrap();

        let saved_field = sm.store.data.get(&test_client_name).unwrap().get(&test_key).unwrap();

        assert_eq!(saved_field, &test_field);
    }

    #[test]
    fn test_delete_value() {
        let tmp_dir = TempDir::new().unwrap();
        let mut sm = get_tmp_store_manager(&tmp_dir);

        let test_client_name = "test_client".to_owned();
        let test_key = "test_key".to_owned();
        let test_field = Value::Boolval(true);

        let mut client_data = HashMap::new();
        client_data.insert(test_key.clone(), clone_value(&test_field).unwrap());

        sm.store.data.insert(test_client_name.clone(), client_data);
        sm.save_store().unwrap();

        sm.delete_value(&test_client_name, &test_key).unwrap();
        assert_eq!(None, sm.store.data.get(&test_client_name).unwrap().get(&test_key));
    }

    #[test]
    fn test_list_prefix() {
        let tmp_dir = TempDir::new().unwrap();
        let mut sm = get_tmp_store_manager(&tmp_dir);

        let test_client_name = "test_client".to_owned();
        let test_field = Value::Boolval(true);

        let mut client_data = HashMap::new();
        client_data.insert("a".to_string(), clone_value(&test_field).unwrap());
        client_data.insert("a/a".to_string(), clone_value(&test_field).unwrap());
        client_data.insert("b".to_string(), clone_value(&test_field).unwrap());

        sm.store.data.insert(test_client_name.clone(), client_data);
        sm.save_store().unwrap();

        let res = sm.list_prefix(&test_client_name, &"a".to_string());
        assert_eq!(2, res.len());
        assert_eq!(
            true,
            res.contains(&ListItem { key: "a".to_string(), type_: ValueType::BoolVal })
        );
        assert_eq!(
            true,
            res.contains(&ListItem { key: "a/a".to_string(), type_: ValueType::BoolVal })
        );
    }

    #[test]
    fn test_get_prefix() {
        let tmp_dir = TempDir::new().unwrap();
        let mut sm = get_tmp_store_manager(&tmp_dir);

        let test_client_name = "test_client".to_owned();
        let test_field = Value::Boolval(true);

        let mut client_data = HashMap::new();
        client_data.insert("a".to_string(), clone_value(&test_field).unwrap());
        client_data.insert("a/a".to_string(), clone_value(&test_field).unwrap());
        client_data.insert("b".to_string(), clone_value(&test_field).unwrap());

        sm.store.data.insert(test_client_name.clone(), client_data);
        sm.save_store().unwrap();

        let res = sm.get_prefix(&test_client_name, &"a".to_string()).unwrap();
        assert_eq!(2, res.len());
        assert_eq!(
            true,
            res.contains(&KeyValue { key: "a".to_string(), val: Value::Boolval(true) })
        );
        assert_eq!(
            true,
            res.contains(&KeyValue { key: "a/a".to_string(), val: Value::Boolval(true) })
        );
    }

    #[test]
    fn test_serialize_deserialize() {
        let tmp_dir = TempDir::new().unwrap();
        let backing_file = tmp_dir.path().join("file.store");
        let test_client = "test_client";

        let mut store = Store::default();
        store.data.insert(test_client.to_string(), HashMap::new());
        store
            .data
            .get_mut(&test_client.to_string())
            .unwrap()
            .insert("int".to_string(), Value::Intval(1));
        store
            .data
            .get_mut(&test_client.to_string())
            .unwrap()
            .insert("float".to_string(), Value::Floatval(1.0));
        store
            .data
            .get_mut(&test_client.to_string())
            .unwrap()
            .insert("bool true".to_string(), Value::Boolval(true));
        store
            .data
            .get_mut(&test_client.to_string())
            .unwrap()
            .insert("bool false".to_string(), Value::Boolval(false));
        store
            .data
            .get_mut(&test_client.to_string())
            .unwrap()
            .insert("string".to_string(), Value::Stringval("test string".to_string()));
        // Value::Bytesval can't be tested here because the vmo handle number changes during the
        // clone operation, making the assert_eq! below fail.

        let clone_store = |_data: &Store| {
            let mut res = HashMap::new();
            for (client_name, client_fields) in store.data.iter() {
                let mut client_data = HashMap::new();
                for (k, v) in client_fields.iter() {
                    client_data.insert(k.clone(), clone_value(v).unwrap());
                }
                res.insert(client_name.clone(), client_data);
            }
            Store { data: res }
        };

        let mut sm_writer = StoreManager::new(backing_file.clone())
            .expect("couldn't make store manager for writing");
        sm_writer.store = clone_store(&store);
        sm_writer.save_store().expect("couldn't save store");

        let sm_reader = StoreManager::new(backing_file.clone())
            .expect("couldn't make store manager from pre-populated file");

        assert_eq!(store, sm_writer.store);
        assert_eq!(store, sm_reader.store);
    }

    #[test]
    fn test_comprehensive() {
        let tmp_dir = TempDir::new().unwrap();
        let mut sm = get_tmp_store_manager(&tmp_dir);

        let test_client_name = "test_client".to_owned();
        let test_key = "test_key".to_owned();
        let test_field = Value::Boolval(true);

        sm.set_value(&test_client_name, test_key.clone(), clone_value(&test_field).unwrap())
            .unwrap();

        assert_eq!(Some(&test_field), sm.get_value(&test_client_name, &test_key));
        assert_eq!(
            vec![ListItem { key: test_key.clone(), type_: ValueType::BoolVal }],
            sm.list_prefix(&test_client_name, &"".to_string())
        );
        assert_eq!(
            vec![KeyValue { key: test_key.clone(), val: Value::Boolval(true) }],
            sm.get_prefix(&test_client_name, &"".to_string()).unwrap()
        );

        sm.delete_value(&test_client_name, &test_key).unwrap();

        assert_eq!(None, sm.get_value(&test_client_name, &test_key));
        assert_eq!(vec![] as Vec<ListItem>, sm.list_prefix(&test_client_name, &"".to_string()));
        assert_eq!(
            vec![] as Vec<KeyValue>,
            sm.get_prefix(&test_client_name, &"".to_string()).unwrap()
        );
    }

    #[test]
    fn test_file_is_updated() {
        let tmp_dir = TempDir::new().unwrap();
        let mut sm = get_tmp_store_manager(&tmp_dir);

        let test_client_name = "test_client".to_owned();
        let file_path = sm.backing_file.clone();

        let mut curr_file_size = 0;
        let mut new_file_size;

        // File shouldn't exist when we start
        assert_eq!(fs::metadata(&file_path).unwrap_err().kind(), io::ErrorKind::NotFound);

        // Set a field, the file size should increase
        sm.set_value(&test_client_name, "foo".to_string(), Value::Boolval(true)).unwrap();
        sm.save_store().unwrap();

        new_file_size = fs::metadata(&file_path).unwrap().len();
        assert!(curr_file_size < new_file_size);
        curr_file_size = new_file_size;

        // Set a different field, the file size should increase
        sm.set_value(&test_client_name, "bar".to_string(), Value::Boolval(true)).unwrap();
        sm.save_store().unwrap();

        new_file_size = fs::metadata(&file_path).unwrap().len();
        assert!(curr_file_size < new_file_size);
        curr_file_size = new_file_size;

        // Delete a field, the file size should decrease
        sm.delete_value(&test_client_name, "bar").unwrap();
        sm.save_store().unwrap();

        new_file_size = fs::metadata(&file_path).unwrap().len();
        assert!(curr_file_size > new_file_size);
        curr_file_size = new_file_size;

        // Delete a field, the file size should decrease
        sm.delete_value(&test_client_name, "foo").unwrap();
        sm.save_store().unwrap();

        new_file_size = fs::metadata(&file_path).unwrap().len();
        assert!(curr_file_size > new_file_size);
    }

    #[test]
    fn test_store_reader_with_client_name_length_error() -> Result<(), Error> {
        let mut types: HashMap<String, Value> = HashMap::new();
        types.insert("integer".to_string(), Value::Intval(42));

        let mut store_bytes = write_tmp_store("test", types)?;
        // Change structure name length to more than the bytes in the buffer
        store_bytes[0] = 255;
        Store::deserialize(store_bytes).unwrap_err();
        Ok(())
    }

    #[test]
    fn test_store_reader_with_key_length_error() -> Result<(), Error> {
        let mut types: HashMap<String, Value> = HashMap::new();
        types.insert("integer".to_string(), Value::Intval(42));

        let mut store_bytes = write_tmp_store("test", types)?;
        // Change key length to more than the bytes in the buffer
        store_bytes[20] = 255;
        Store::deserialize(store_bytes).unwrap_err();
        Ok(())
    }

    #[test]
    fn test_store_reader_with_value_length_error() -> Result<(), Error> {
        let mut types: HashMap<String, Value> = HashMap::new();
        types.insert("integer".to_string(), Value::Intval(42));

        let mut store_bytes = write_tmp_store("test", types)?;
        // Change value length to more than the bytes in the buffer
        store_bytes[36] = 255;
        Store::deserialize(store_bytes).unwrap_err();
        Ok(())
    }

    #[test]
    fn test_stash_reader_with_value_length_exact_length() -> Result<(), Error> {
        let mut types: HashMap<String, Value> = HashMap::new();
        types.insert("integer".to_string(), Value::Intval(42));

        let mut store_bytes = write_tmp_store("test", types)?;
        // Use exact length, this should be ok.
        store_bytes[36] = 8; // It's already 8 but it keeps it consistent with the other tests.
        Store::deserialize(store_bytes).unwrap();
        Ok(())
    }

    #[test]
    fn test_stash_reader_with_value_length_one_over_length() -> Result<(), Error> {
        let mut types: HashMap<String, Value> = HashMap::new();
        types.insert("integer".to_string(), Value::Intval(42));

        let mut store_bytes = write_tmp_store("test", types)?;
        // Change value length to one more than the bytes in the buffer
        store_bytes[36] = 9;
        Store::deserialize(store_bytes).unwrap_err();
        Ok(())
    }
}
