/* Code generated by Azure.Iot.Operations.ProtocolCompilerLib v1.0.0.0; DO NOT EDIT. */

use std::collections::HashMap;
use std::time::Duration;

use azure_iot_operations_mqtt::control_packet::QoS;
use azure_iot_operations_mqtt::session::SessionManagedClient;
use azure_iot_operations_protocol::application::ApplicationContext;
use azure_iot_operations_protocol::common::aio_protocol_error::AIOProtocolError;
use azure_iot_operations_protocol::common::payload_serialize::PayloadSerialize;
use azure_iot_operations_protocol::telemetry;

use super::super::common_types::options::TelemetrySenderOptions;
use super::dataset_runtime_health_event_telemetry::DatasetRuntimeHealthEventTelemetry;

pub type DatasetRuntimeHealthEventTelemetryMessage =
    telemetry::sender::Message<DatasetRuntimeHealthEventTelemetry>;
pub type DatasetRuntimeHealthEventTelemetryMessageBuilderError =
    telemetry::sender::MessageBuilderError;

/// Builder for [`DatasetRuntimeHealthEventTelemetryMessage`]
#[derive(Default)]
pub struct DatasetRuntimeHealthEventTelemetryMessageBuilder {
    inner_builder: telemetry::sender::MessageBuilder<DatasetRuntimeHealthEventTelemetry>,
    topic_tokens: HashMap<String, String>,
}

impl DatasetRuntimeHealthEventTelemetryMessageBuilder {
    /// Quality of Service of the telemetry message. Can only be `AtMostOnce` or `AtLeastOnce`.
    pub fn qos(&mut self, qos: QoS) -> &mut Self {
        self.inner_builder.qos(qos);
        self
    }

    /// Custom user data to set on the message
    pub fn custom_user_data(&mut self, custom_user_data: Vec<(String, String)>) -> &mut Self {
        self.inner_builder.custom_user_data(custom_user_data);
        self
    }

    /// Topic token keys/values to be replaced into the publish topic of the telemetry message.
    /// A prefix of "ex:" will be prepended to each key before scanning the topic pattern.
    /// Thus, only tokens of the form `{ex:SOMEKEY}` will be replaced.
    pub fn topic_tokens(&mut self, topic_tokens: HashMap<String, String>) -> &mut Self {
        for (k, v) in topic_tokens {
            self.topic_tokens.insert(format!("ex:{k}"), v);
        }
        self
    }

    /// Time before message expires
    pub fn message_expiry(&mut self, message_expiry: Duration) -> &mut Self {
        self.inner_builder.message_expiry(message_expiry);
        self
    }

    /// Cloud event for the message
    pub fn cloud_event(&mut self, cloud_event: Option<telemetry::sender::CloudEvent>) -> &mut Self {
        self.inner_builder.cloud_event(cloud_event);
        self
    }

    /// Payload of the message
    ///
    /// # Errors
    /// If the payload cannot be serialized
    pub fn payload(
        &mut self,
        payload: DatasetRuntimeHealthEventTelemetry,
    ) -> Result<&mut Self, AIOProtocolError> {
        self.inner_builder.payload(payload)?;
        Ok(self)
    }

    /// Builds a new `DatasetRuntimeHealthEventTelemetryMessage`
    ///
    /// # Errors
    /// If a required field has not been initialized
    pub fn build(
        &mut self,
    ) -> Result<
        DatasetRuntimeHealthEventTelemetryMessage,
        DatasetRuntimeHealthEventTelemetryMessageBuilderError,
    > {
        self.inner_builder.topic_tokens(self.topic_tokens.clone());

        self.inner_builder.build()
    }
}

/// Telemetry Sender for `DatasetRuntimeHealthEventTelemetry`
pub struct DatasetRuntimeHealthEventTelemetrySender(
    telemetry::Sender<DatasetRuntimeHealthEventTelemetry>,
);

impl DatasetRuntimeHealthEventTelemetrySender {
    /// Creates a new [`DatasetRuntimeHealthEventTelemetrySender`]
    ///
    /// # Panics
    /// If the DTDL that generated this code was invalid
    pub fn new(
        application_context: ApplicationContext,
        client: SessionManagedClient,
        options: &TelemetrySenderOptions,
    ) -> Self {
        let mut sender_options_builder = telemetry::sender::OptionsBuilder::default();
        if let Some(topic_namespace) = &options.topic_namespace {
            sender_options_builder.topic_namespace(topic_namespace.clone());
        }

        let mut topic_token_map: HashMap<String, String> = options
            .topic_token_map
            .clone()
            .into_iter()
            .map(|(k, v)| (format!("ex:{k}"), v))
            .collect();

        topic_token_map.insert("senderId".to_string(), client.client_id().to_string());

        let sender_options = sender_options_builder
            .topic_pattern("akri/connector/resources/telemetry/{ex:connectorClientId}/{ex:deviceName}/{ex:inboundEndpointName}/datasetRuntimeHealthEvent")
            .topic_token_map(topic_token_map)
            .build()
            .expect("DTDL schema generated invalid arguments");

        Self(
            telemetry::Sender::new(application_context, client, sender_options)
                .expect("DTDL schema generated invalid arguments"),
        )
    }

    /// Sends a [`DatasetRuntimeHealthEventTelemetryMessage`]
    ///
    /// # Error
    /// [`AIOProtocolError`] if there is a failure sending the message
    pub async fn send(
        &self,
        message: DatasetRuntimeHealthEventTelemetryMessage,
    ) -> Result<(), AIOProtocolError> {
        self.0.send(message).await
    }
}
