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

pub type ComponentInstanceId = String;

#[derive(Debug, Clone, Error)]
pub enum ComponentIdIndexError {
    #[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),
}

/// ComponentIdIndex parses a given index and provides methods to look up instance IDs.
#[derive(Debug, Default)]
pub struct ComponentIdIndex {
    _moniker_to_instance_id: HashMap<AbsoluteMoniker, ComponentInstanceId>,
}

impl ComponentIdIndex {
    pub async fn new(index_file_path: &str) -> Result<Self, ComponentIdIndexError> {
        let fidl_index = io_util::file::read_in_namespace_to_fidl::<
            fcomponent_internal::ComponentIdIndex,
        >(index_file_path)
        .await
        .map_err(|err| ComponentIdIndexError::IndexUnreadable {
            path: index_file_path.to_string(),
            err: err.into(),
        })?;

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

        let mut moniker_to_instance_id = HashMap::<AbsoluteMoniker, ComponentInstanceId>::new();
        for entry in &index.instances {
            if let Some(moniker) = &entry.moniker {
                let absolute_moniker = AbsoluteMoniker::parse_string_without_instances(moniker)
                    .map_err(|e| ComponentIdIndexError::MonikerError(e))?;
                moniker_to_instance_id.insert(
                    absolute_moniker,
                    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(),
                );
            }
        }
        Ok(Self { _moniker_to_instance_id: moniker_to_instance_id })
    }

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

#[cfg(test)]
pub mod tests {
    use super::*;
    use anyhow::Result;
    use fidl::encoding::encode_persistent;
    use fuchsia_async as fasync;
    use std::convert::TryFrom;
    use std::io::Write;
    use tempfile::NamedTempFile;

    fn make_index_file(index: component_id_index::Index) -> Result<NamedTempFile> {
        let mut tmp_file = NamedTempFile::new()?;
        tmp_file.write_all(
            encode_persistent(&mut fcomponent_internal::ComponentIdIndex::try_from(index)?)?
                .as_ref(),
        )?;
        Ok(tmp_file)
    }

    #[fasync::run_singlethreaded(test)]
    async fn invalid_moniker() {
        let index_file = make_index_file(component_id_index::Index {
            instances: vec![component_id_index::InstanceIdEntry {
                instance_id: Some("0".repeat(64)),
                appmgr_moniker: None,
                moniker: Some("invalid moniker".to_string()),
            }],
            ..component_id_index::Index::default()
        })
        .unwrap();

        let moniker = ComponentIdIndex::new(index_file.path().to_str().unwrap()).await;
        assert!(matches!(
            moniker.err().unwrap(),
            ComponentIdIndexError::MonikerError(MonikerError::InvalidMoniker { rep: _ }),
        ));
    }

    #[fasync::run_singlethreaded(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_string_without_instances("/a/b/c").unwrap())
            .is_none());
    }

    #[fasync::run_singlethreaded(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("/a/b/c".to_string()),
            }],
            ..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_string_without_instances("/a/b/c").unwrap()
            )
        );
    }

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