// 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 {
    crate::{
        capability::*,
        channel,
        model::{
            error::ModelError,
            hooks::{Event, EventPayload, EventType, Hook, HooksRegistration},
        },
    },
    anyhow::{format_err, Error},
    async_trait::async_trait,
    fidl::endpoints::{ServerEnd, ServiceMarker},
    fuchsia_async as fasync,
    fuchsia_zircon::{self as zx, ResourceInfo},
    log::warn,
    std::{
        path::PathBuf,
        sync::{Arc, Weak},
    },
};

/// A builtin capability, whether it be a `framework` capability
/// or a capability that originates above the root realm (from component_manager).
///
/// Implementing this trait takes care of certain boilerplate, like registering
/// event hooks and the creation of a CapabilityProvider.
#[async_trait]
pub trait BuiltinCapability {
    /// Name of the capability. Used for hook registration and logging.
    const NAME: &'static str;

    /// Service marker for the capability.
    type Marker: ServiceMarker;

    /// Serves an instance of the capability given an appropriate RequestStream.
    /// Returns when the channel backing the RequestStream is closed or an
    /// unrecoverable error occurs.
    async fn serve(
        self: Arc<Self>,
        mut stream: <Self::Marker as ServiceMarker>::RequestStream,
    ) -> Result<(), Error>;

    /// Returns the registration hooks for the capability.
    fn hooks(self: &Arc<Self>) -> Vec<HooksRegistration>
    where
        Self: 'static + Hook + Sized,
    {
        vec![HooksRegistration::new(
            Self::NAME,
            vec![EventType::CapabilityRouted],
            Arc::downgrade(self) as Weak<dyn Hook>,
        )]
    }

    /// Returns true if the builtin capability matches the requested `capability`
    /// and should be served.
    fn matches_routed_capability(&self, capability: &InternalCapability) -> bool;
}

#[async_trait]
pub trait ResourceCapability {
    /// The kind of resource.
    const KIND: zx::sys::zx_rsrc_kind_t;

    /// Name of the capability. Used for hook registration and logging.
    const NAME: &'static str;

    /// Service marker for the capability.
    type Marker: ServiceMarker;

    fn get_resource_info(self: &Arc<Self>) -> Result<ResourceInfo, Error>;

    async fn server_loop(
        self: Arc<Self>,
        mut stream: <Self::Marker as ServiceMarker>::RequestStream,
    ) -> Result<(), Error>;

    fn matches_routed_capability(&self, capability: &InternalCapability) -> bool;
}

#[async_trait]
impl<R: ResourceCapability + Send + Sync> BuiltinCapability for R {
    const NAME: &'static str = R::NAME;
    type Marker = R::Marker;

    async fn serve(
        self: Arc<Self>,
        stream: <R::Marker as ServiceMarker>::RequestStream,
    ) -> Result<(), Error> {
        let resource_info = self.get_resource_info()?;
        if (resource_info.kind != R::KIND || resource_info.base != 0 || resource_info.size != 0) {
            return Err(format_err!("{} not available.", R::NAME));
        }
        self.server_loop(stream).await
    }

    fn matches_routed_capability(&self, capability: &InternalCapability) -> bool {
        self.matches_routed_capability(capability)
    }
}

#[async_trait]
impl<B: 'static + BuiltinCapability + Send + Sync> Hook for B {
    async fn on(self: Arc<Self>, event: &Event) -> Result<(), ModelError> {
        if let Ok(EventPayload::CapabilityRouted {
            source: CapabilitySource::Builtin { capability },
            capability_provider,
        }) = &event.result
        {
            if self.matches_routed_capability(&capability) {
                let mut provider = capability_provider.lock().await;
                *provider =
                    Some(Box::new(BuiltinCapabilityProvider::<B>::new(Arc::downgrade(&self))));
            }
        }
        Ok(())
    }
}

struct BuiltinCapabilityProvider<B: BuiltinCapability> {
    capability: Weak<B>,
}

impl<B: BuiltinCapability> BuiltinCapabilityProvider<B> {
    pub fn new(capability: Weak<B>) -> Self {
        Self { capability }
    }
}

#[async_trait]
impl<B: 'static + BuiltinCapability + Sync + Send> CapabilityProvider
    for BuiltinCapabilityProvider<B>
{
    async fn open(
        self: Box<Self>,
        _flags: u32,
        _open_mode: u32,
        _relative_path: PathBuf,
        server_end: &mut zx::Channel,
    ) -> Result<(), ModelError> {
        let server_end = channel::take_channel(server_end);
        let server_end = ServerEnd::<B::Marker>::new(server_end);
        let stream = server_end.into_stream().map_err(ModelError::stream_creation_error)?;
        fasync::Task::spawn(async move {
            if let Some(capability) = self.capability.upgrade() {
                if let Err(err) = capability.serve(stream).await {
                    warn!("{}::open failed: {}", B::NAME, err);
                }
            } else {
                warn!("{} has been dropped", B::NAME);
            }
        })
        .detach();
        Ok(())
    }
}
