// 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 {
    anyhow,
    clonable_error::ClonableError,
    component_id_index, fidl,
    fidl::encoding::decode_persistent,
    fidl_fuchsia_component_internal as fcomponent_internal,
    moniker::{AbsoluteMoniker, MonikerError},
    std::collections::{HashMap, HashSet},
    thiserror::Error,
};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

pub type ComponentInstanceId = String;

#[cfg_attr(feature = "serde", derive(Deserialize, Serialize), serde(rename_all = "snake_case"))]
#[derive(Debug, Clone, Error)]
pub enum ComponentIdIndexError {
    // The capability routing static analyzer does not report this error subtype as part of a
    // routing verification result, so we don't need to serialize it.
    #[cfg_attr(feature = "serde", serde(skip))]
    #[error("could not read index file {}", .path)]
    IndexUnreadable {
        #[source]
        err: ClonableError,
        path: String,
    },
    #[error("Index error")]
    IndexError(#[from] component_id_index::IndexError),
    #[error("invalid moniker")]
    MonikerError(#[from] MonikerError),
}

impl ComponentIdIndexError {
    pub fn index_unreadable(
        index_file_path: impl Into<String>,
        err: impl Into<anyhow::Error>,
    ) -> Self {
        ComponentIdIndexError::IndexUnreadable {
            path: index_file_path.into(),
            err: err.into().into(),
        }
    }
}

// Custom implementation of PartialEq in which two ComponentIdIndexError::IndexUnreadable errors are
// never equal.
impl PartialEq for ComponentIdIndexError {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Self::IndexError(self_err), Self::IndexError(other_err)) => self_err.eq(other_err),
            (Self::MonikerError(self_err), Self::MonikerError(other_err)) => self_err.eq(other_err),
            (Self::IndexUnreadable { .. }, Self::IndexUnreadable { .. }) => false,
            _ => false,
        }
    }
}

/// ComponentIdIndex parses a given index and provides methods to look up instance IDs.
#[derive(Debug, Default)]
pub struct ComponentIdIndex {
    /// Map of a moniker from the index to its instance ID.
    ///
    /// The moniker does not contain instances, i.e. all of the ChildMonikers in the
    /// path have the (moniker, not index) instance ID set to zero.
    moniker_to_instance_id: HashMap<AbsoluteMoniker, ComponentInstanceId>,

    /// Stores all instance IDs from the index.
    /// This is used by StorageAdmin for methods that operate directly on instance IDs.
    ///
    /// This set will currently contain all storage IDs, even of components registered with appmgr
    /// instead of component_manager. This is desired because it allows the StorageAdmin protocol
    /// to handle all storage on the system.
    all_instance_ids: HashSet<ComponentInstanceId>,
}

impl ComponentIdIndex {
    pub async fn new(index_file_path: &str) -> Result<Self, ComponentIdIndexError> {
        let raw_content = std::fs::read(index_file_path)
            .map_err(|err| ComponentIdIndexError::index_unreadable(index_file_path, err))?;

        let fidl_index =
            decode_persistent::<fcomponent_internal::ComponentIdIndex>(&raw_content)
                .map_err(|err| ComponentIdIndexError::index_unreadable(index_file_path, err))?;

        let index = component_id_index::Index::from_fidl(fidl_index)?;
        Self::new_from_index(index)
    }

    pub fn new_from_index(index: component_id_index::Index) -> Result<Self, ComponentIdIndexError> {
        let mut moniker_to_instance_id = HashMap::<AbsoluteMoniker, ComponentInstanceId>::new();
        let mut all_instance_ids = HashSet::new();
        for entry in index.instances {
            let instance_id = entry
                .instance_id
                .as_ref()
                .ok_or_else(|| {
                    ComponentIdIndexError::IndexError(
                        component_id_index::IndexError::ValidationError(
                            component_id_index::ValidationError::MissingInstanceIds {
                                entries: vec![entry.clone()],
                            },
                        ),
                    )
                })?
                .clone();

            all_instance_ids.insert(instance_id.clone());
            if let Some(absolute_moniker) = entry.moniker {
                moniker_to_instance_id.insert(absolute_moniker, instance_id);
            }
        }
        Ok(Self { moniker_to_instance_id, all_instance_ids })
    }

    pub fn look_up_moniker(&self, moniker: &AbsoluteMoniker) -> Option<&ComponentInstanceId> {
        self.moniker_to_instance_id.get(&moniker)
    }

    pub fn look_up_instance_id(&self, id: &ComponentInstanceId) -> bool {
        self.all_instance_ids.contains(id)
    }
}

#[cfg(test)]
pub mod tests {
    use super::*;
    use moniker::{AbsoluteMonikerBase, ChildMoniker};
    use routing_test_helpers::component_id_index::make_index_file;

    #[fuchsia::test]
    async fn look_up_moniker_no_exists() {
        let index_file = make_index_file(component_id_index::Index::default()).unwrap();
        let index = ComponentIdIndex::new(index_file.path().to_str().unwrap()).await.unwrap();
        assert!(index.look_up_moniker(&AbsoluteMoniker::parse_str("/a/b/c").unwrap()).is_none());
    }

    #[fuchsia::test]
    async fn look_up_moniker_exists() {
        let iid = "0".repeat(64);
        let index_file = make_index_file(component_id_index::Index {
            instances: vec![component_id_index::InstanceIdEntry {
                instance_id: Some(iid.clone()),
                appmgr_moniker: None,
                moniker: Some(AbsoluteMoniker::parse_str("/a/b/c").unwrap()),
            }],
            ..component_id_index::Index::default()
        })
        .unwrap();
        let index = ComponentIdIndex::new(index_file.path().to_str().unwrap()).await.unwrap();
        assert_eq!(
            Some(&iid),
            index.look_up_moniker(&AbsoluteMoniker::parse_str("/a/b/c").unwrap())
        );
    }

    #[fuchsia::test]
    async fn look_up_moniker_with_instances_exists() {
        let iid = "0".repeat(64);
        let index_file = make_index_file(component_id_index::Index {
            instances: vec![component_id_index::InstanceIdEntry {
                instance_id: Some(iid.clone()),
                appmgr_moniker: None,
                moniker: Some(AbsoluteMoniker::parse_str("/a/coll:name").unwrap()),
            }],
            ..component_id_index::Index::default()
        })
        .unwrap();
        let index = ComponentIdIndex::new(index_file.path().to_str().unwrap()).await.unwrap();
        assert_eq!(
            Some(&iid),
            index.look_up_moniker(&AbsoluteMoniker::new(vec![
                ChildMoniker::new("a".to_string(), None),
                ChildMoniker::new("name".to_string(), Some("coll".to_string())),
            ]))
        );
    }

    #[fuchsia::test]
    fn new_from_index() {
        let iid = "0".repeat(64);
        let inner_index = component_id_index::Index {
            instances: vec![component_id_index::InstanceIdEntry {
                instance_id: Some(iid.clone()),
                appmgr_moniker: None,
                moniker: Some(AbsoluteMoniker::parse_str("/a/b/c").unwrap()),
            }],
            ..component_id_index::Index::default()
        };
        let index = ComponentIdIndex::new_from_index(inner_index)
            .expect("failed to create component id index from inner index");
        assert_eq!(
            Some(&iid),
            index.look_up_moniker(&AbsoluteMoniker::parse_str("/a/b/c").unwrap())
        );
    }

    #[fuchsia::test]
    async fn index_unreadable() {
        let result = ComponentIdIndex::new("/this/path/doesnt/exist").await;
        assert!(matches!(result, Err(ComponentIdIndexError::IndexUnreadable { path: _, err: _ })));
    }
}
