// Copyright 2021 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.

//! Service-wide MessageHub definition.
//!
//! The service mod defines a MessageHub (and associated Address, Payload, and
//! Role namespaces) to facilitate service-wide communication. All
//! communication, both intra-component and inter-component, should be sent
//! through this hub. The address space of this MessageHub allows any component
//! to be reached when given a public address. The Role space allows granular
//! message filtering and audience targeting.
//!
//! The static Address and Role definitions below provide a way to reference
//! such values at build time. However, many use-cases that rely on these
//! features can be done through values generated at runtime instead. Care
//! should be taken before expanding either enumeration.
//!
//! Currently, service communication happens in a number of domain-specific
//! message hubs located in the internal mod. Communication from these hubs
//! should migrate here over time.

use crate::base::SettingType;
use crate::handler::{base as handler, setting_handler as controller};
use crate::message::message_hub;
use crate::{agent, event, job, storage};

pub struct MessageHub;

impl MessageHub {
    pub(crate) fn create_hub() -> message::Delegate {
        message_hub::MessageHub::create()
    }
}

pub(crate) mod message {
    use crate::message::{base, delegate, message_client, messenger, receptor};

    pub(crate) type Delegate = delegate::Delegate;
    pub(crate) type Audience = base::Audience;
    pub(crate) type Messenger = messenger::MessengerClient;
    pub(crate) type MessageError = base::MessageError;
    pub(crate) type MessageEvent = base::MessageEvent;
    pub(crate) type MessageClient = message_client::MessageClient;
    pub(crate) type MessengerType = base::MessengerType;
    pub(crate) type Receptor = receptor::Receptor;
    pub(crate) type Signature = base::Signature;
}

/// The `Address` enumeration defines a namespace for entities that can be
/// reached by a predefined name. Care should be taken when adding new child
/// namespaces here. Each address can only belong to a single entity.
/// Most communication can be instead facilitated with a messenger's signature,
/// which is available at messenger creation time.
#[derive(PartialEq, Copy, Clone, Debug, Eq, Hash)]
pub enum Address {
    Handler(SettingType),
    EventSource(event::Address),
    Storage,
    /// This value is reserved for testing purposes.
    #[cfg(test)]
    Test(u64),
}

/// The types of data that can be sent through the service `MessageHub`. This
/// enumeration is meant to provide a top level definition. Further definitions
/// for particular domains should be located in the appropriate mod.
#[derive(Clone, PartialEq, Debug)]
pub enum Payload {
    /// The Setting type captures communication pertaining to settings,
    /// including requests to access/change settings and the associated
    /// responses.
    Setting(handler::Payload),
    /// The communication to and from a controller to handle requests and
    /// lifetime.
    Controller(controller::Payload),
    /// Agent payloads contain communication between the agent authority and individual agents.
    Agent(agent::Payload),
    /// Event payloads contain data about events that occur throughout the system.
    Event(event::Payload),
    /// Job payloads contain information related to new sources of jobs to be executed.
    Job(job::Payload),
    /// Storage payloads contain read and write requests to storage and their responses.
    Storage(storage::Payload),
    /// This value is reserved for testing purposes.
    #[cfg(test)]
    Test(test::Payload),
}

#[cfg(test)]
pub(crate) mod test {
    use crate::audio::types::AudioInfo;
    use crate::payload_convert;

    /// This payload should be expanded to include any sort of data that tests would send that is
    /// outside the scope of production payloads.
    #[derive(PartialEq, Clone, Debug)]
    pub enum Payload {
        Integer(i64),
        Audio(AudioInfo),
    }

    // Conversions for Handler Payload.
    payload_convert!(Test, Payload);
}

/// A trait implemented by payloads for extracting the payload and associated
/// [`message::MessageClient`] from a [`crate::message::base::MessageEvent`].
pub(crate) trait TryFromWithClient<T>: Sized {
    type Error;

    fn try_from_with_client(value: T) -> Result<(Self, message::MessageClient), Self::Error>;
}

/// The payload_convert macro helps convert between the domain-specific payloads
/// (variants of [`Payload`]) and the [`Payload`] container(to/from) & MessageHub
/// MessageEvent (from). The first matcher is the [`Payload`] variant name where
/// the payload type can be found. Note that this is the direct variant name
/// and not fully qualified. The second matcher is the domain-specific payload
/// type.
///
/// The macro implements the following in a mod called convert:
/// - Into from domain Payload to service MessageHub Payload
/// - TryFrom from service MessageHub Payload to domain Payload
/// - TryFromWithClient from service MessageHub MessageEvent to domain Payload
///   and client.
/// - TryFromWithClient from a service MessageHub MessageEvent option to domain
///   Payload and client.
#[macro_export]
macro_rules! payload_convert {
    ($service_payload_type:ident, $payload_type:ty) => {
        pub(super) mod convert {
            use super::*;
            use $crate::service;
            use $crate::service::TryFromWithClient;

            impl From<$payload_type> for service::Payload {
                fn from(payload: $payload_type) -> service::Payload {
                    paste::paste! {
                        service::Payload::[<$service_payload_type>](payload)
                    }
                }
            }

            impl TryFrom<service::Payload> for $payload_type {
                type Error = String;

                fn try_from(value: service::Payload) -> Result<Self, Self::Error> {
                    paste::paste! {
                        match value {
                            service::Payload::[<$service_payload_type>](payload) => Ok(payload),
                            _=> Err(format!("unexpected payload encountered: {:?}", value)),
                        }
                    }
                }
            }

            impl TryFrom<service::message::MessageEvent> for $payload_type {
                type Error = String;

                fn try_from(value: service::message::MessageEvent) -> Result<Self, Self::Error> {
                    paste::paste! {
                        if let service::message::MessageEvent::Message(payload, _) = value {
                            Payload::try_from(payload)
                        } else {
                            Err(String::from("wrong message type"))
                        }
                    }
                }
            }

            impl TryFromWithClient<service::message::MessageEvent> for $payload_type {
                type Error = String;

                fn try_from_with_client(
                    value: service::message::MessageEvent,
                ) -> Result<(Self, service::message::MessageClient), Self::Error> {
                    if let service::message::MessageEvent::Message(payload, client) = value {
                        Ok((Payload::try_from(payload)?, client))
                    } else {
                        Err(String::from("wrong message type"))
                    }
                }
            }
        }
    };
}

#[cfg(test)]
pub(crate) async fn build_event_listener(delegate: &message::Delegate) -> message::Receptor {
    delegate.create_sink().await.expect("Should be able to retrieve receptor").1
}
