// 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::base::SettingType;
use crate::event;
use crate::message::base::MessengerType;
use crate::monitor;
use crate::payload_convert;
use crate::service;
use crate::service::message::Receptor;
use crate::service_context::ServiceContext;

use futures::future::BoxFuture;
use std::collections::HashSet;
use std::fmt::Debug;
use std::sync::Arc;
use thiserror::Error;

/// Agent for watching the camera3 status.
pub mod camera_watcher;

/// Agent for handling media button input.
pub mod media_buttons;

/// This mod provides a concrete implementation of the agent authority.
pub mod authority;

/// Agent for rehydrating actions for restore.
pub mod restore_agent;

// Agent for managing access to storage.
pub mod storage_agent;

/// Agent for capturing requests.
pub mod inspect;

/// Earcons.
pub mod earcons;

/// Agent for capturing policy state from messages from the message hub to
/// policy proxies.
pub mod inspect_policy;

/// Agent for capturing setting values of messages between proxies and setting
/// handlers.
pub mod inspect_setting_data;

#[derive(Error, Debug, Clone, Copy, PartialEq)]
pub enum AgentError {
    #[error("Unhandled Lifespan")]
    UnhandledLifespan,
    #[error("Unexpected Error")]
    UnexpectedError,
}

pub type InvocationResult = Result<(), AgentError>;

/// The scope of an agent's life. Initialization components should
/// only run at the beginning of the service. Service components follow
/// initialization and run for the duration of the service.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Lifespan {
    Initialization,
    Service,
}

/// Struct of information passed to the agent during each invocation.
#[derive(Clone)]
pub struct Invocation {
    pub lifespan: Lifespan,
    pub service_context: Arc<ServiceContext>,
}

impl Debug for Invocation {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("Invocation").field("lifespan", &self.lifespan).finish_non_exhaustive()
    }
}

impl PartialEq for Invocation {
    fn eq(&self, other: &Self) -> bool {
        self.lifespan == other.lifespan
    }
}

/// Blueprint defines an interface provided to the authority for constructing
/// a given agent.
pub trait Blueprint {
    /// Uses the supplied context to create agent.
    fn create(&self, context: Context) -> BoxFuture<'static, ()>;
}

pub type BlueprintHandle = Arc<dyn Blueprint + Send + Sync>;

/// TODO(fxbug.dev/68659): Add documentation.
pub struct Context {
    pub receptor: Receptor,
    publisher: event::Publisher,
    pub messenger_factory: service::message::Factory,
    pub available_components: HashSet<SettingType>,
    pub resource_monitor_actor: Option<monitor::environment::Actor>,
}

impl Context {
    pub async fn new(
        receptor: Receptor,
        messenger_factory: service::message::Factory,
        available_components: HashSet<SettingType>,
        resource_monitor_actor: Option<monitor::environment::Actor>,
    ) -> Self {
        let publisher = event::Publisher::create(&messenger_factory, MessengerType::Unbound).await;
        Self {
            receptor,
            publisher,
            messenger_factory,
            available_components,
            resource_monitor_actor,
        }
    }

    /// Generates a new `Messenger` on the service `MessageHub`. Only
    /// top-level messages can be sent, not received, as the associated
    /// `Receptor` is discarded.
    pub async fn create_messenger(
        &self,
    ) -> Result<service::message::Messenger, service::message::MessageError> {
        Ok(self.messenger_factory.create(MessengerType::Unbound).await?.0)
    }

    pub fn get_publisher(&self) -> event::Publisher {
        self.publisher.clone()
    }
}

#[macro_export]
macro_rules! blueprint_definition {
    ($component:expr, $create:expr) => {
        pub mod blueprint {
            #[allow(unused_imports)]
            use super::*;
            use crate::agent::{Blueprint, BlueprintHandle, Context};
            use futures::future::BoxFuture;
            use std::sync::Arc;

            pub fn create() -> BlueprintHandle {
                Arc::new(BlueprintImpl)
            }

            struct BlueprintImpl;

            impl Blueprint for BlueprintImpl {
                fn create(&self, context: Context) -> BoxFuture<'static, ()> {
                    Box::pin(async move {
                        $create(context).await;
                    })
                }
            }
        }
    };
}

#[derive(Clone, Debug, PartialEq)]
pub enum Payload {
    Invocation(Invocation),
    Complete(InvocationResult),
}

payload_convert!(Agent, Payload);
