// Copyright 2019 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::config::RuntimeConfig,
    crate::model::{
        actions::{ActionKey, DiscoverAction},
        binding::Binder,
        component::{BindReason, ComponentInstance, ComponentManagerInstance},
        context::ModelContext,
        environment::Environment,
        error::ModelError,
    },
    moniker::AbsoluteMoniker,
    std::sync::Arc,
};

/// Parameters for initializing a component model, particularly the root of the component
/// instance tree.
pub struct ModelParams {
    // TODO(viktard): Merge into RuntimeConfig
    /// The URL of the root component.
    pub root_component_url: String,
    /// The environment provided to the root.
    pub root_environment: Environment,
    /// Global runtime configuration for the component_manager.
    pub runtime_config: Arc<RuntimeConfig>,
    /// The instance at the top of the tree, representing component manager.
    pub top_instance: Arc<ComponentManagerInstance>,
}

/// The component model holds authoritative state about a tree of component instances, including
/// each instance's identity, lifecycle, capabilities, and topological relationships.  It also
/// provides operations for instantiating, destroying, querying, and controlling component
/// instances at runtime.
pub struct Model {
    pub root: Arc<ComponentInstance>,
    _context: Arc<ModelContext>,
    _top_instance: Arc<ComponentManagerInstance>,
}

impl Model {
    /// Creates a new component model and initializes its topology.
    pub async fn new(params: ModelParams) -> Result<Arc<Model>, ModelError> {
        let context = Arc::new(ModelContext::new(params.runtime_config).await?);
        let root = ComponentInstance::new_root(
            params.root_environment,
            Arc::downgrade(&context),
            Arc::downgrade(&params.top_instance),
            params.root_component_url,
        );
        Ok(Arc::new(Model { root, _context: context, _top_instance: params.top_instance }))
    }

    /// Looks up a component by absolute moniker. The component instance in the component will be
    /// resolved if that has not already happened.
    pub async fn look_up(
        &self,
        look_up_abs_moniker: &AbsoluteMoniker,
    ) -> Result<Arc<ComponentInstance>, ModelError> {
        let mut cur = self.root.clone();
        for moniker in look_up_abs_moniker.path().iter() {
            cur = {
                let cur_state = cur.lock_resolved_state().await?;
                if let Some(r) = cur_state.all_children().get(moniker) {
                    r.clone()
                } else {
                    return Err(ModelError::instance_not_found(look_up_abs_moniker.clone()));
                }
            };
        }
        let _ = cur.lock_resolved_state().await?;
        Ok(cur)
    }

    /// Binds to the root, starting the component tree.
    pub async fn start(self: &Arc<Model>) {
        // Normally the Discovered event is dispatched when an instance is added as a child, but
        // since the root isn't anyone's child we need to dispatch it here.
        {
            let mut actions = self.root.lock_actions().await;
            let _ = actions.register_no_wait(&self.root, DiscoverAction::new());
        }
        if let Err(e) = self.bind(&AbsoluteMoniker::root(), &BindReason::Root).await {
            // If we fail binding to the root, but the root is being shutdown, that's ok. The
            // system is tearing down, so it doesn't matter any more if we never got everything
            // started that we wanted to.
            let action_set = self.root.lock_actions().await;
            if !action_set.contains(&ActionKey::Shutdown) {
                panic!("failed to bind to root component {}: {:?}", self.root.component_url, e);
            }
        }
    }
}

#[cfg(test)]
pub mod tests {
    use {
        crate::{
            model::actions::ShutdownAction,
            model::testing::test_helpers::{
                ComponentDeclBuilder, TestEnvironmentBuilder, TestModelResult,
            },
        },
        fidl_fuchsia_sys2 as fsys,
    };

    #[fuchsia::test]
    async fn shutting_down_when_start_fails() {
        let components = vec![(
            "root",
            ComponentDeclBuilder::new()
                .add_child(cm_rust::ChildDecl {
                    name: "bad-scheme".to_string(),
                    url: "bad-scheme://sdf".to_string(),
                    startup: fsys::StartupMode::Eager,
                    environment: None,
                })
                .build(),
        )];

        let TestModelResult { model, .. } =
            TestEnvironmentBuilder::new().set_components(components).build().await;

        let _ = model.root.lock_actions().await.register_inner(&model.root, ShutdownAction::new());

        model.start().await;
    }

    #[should_panic]
    #[fuchsia::test]
    async fn not_shutting_down_when_start_fails() {
        let components = vec![(
            "root",
            ComponentDeclBuilder::new()
                .add_child(cm_rust::ChildDecl {
                    name: "bad-scheme".to_string(),
                    url: "bad-scheme://sdf".to_string(),
                    startup: fsys::StartupMode::Eager,
                    environment: None,
                })
                .build(),
        )];

        let TestModelResult { model, .. } =
            TestEnvironmentBuilder::new().set_components(components).build().await;

        model.start().await;
    }
}
