righvalor 0.1.0

RighValor: AI Infrastructure and Applications Framework for the Far Edge
use std::path::PathBuf;

use anyhow::{anyhow, Result};
use righ_dm_rs::RighVersion;
use serde::{Deserialize, Serialize};

use crate::{
    runtime::ValorRuntimeEngine,
    service::{ValorServiceEntity, ValorServiceId},
};

/// # Valor Righ Device Classification Service
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValorRighDeviceClassificationService {
    runtime: ValorRuntimeEngine,
    version: RighVersion,
    metadata: Vec<u8>,
    model_path: Option<PathBuf>,
}

impl ValorRighDeviceClassificationService {
    /// Create a new builder for `ValorRighDeviceClassificationService`.
    #[must_use]
    pub fn builder() -> ValorRighDeviceClassificationServiceBuilder {
        ValorRighDeviceClassificationServiceBuilder::default()
    }
}

/// Builder for ValorRighDeviceClassificationService.
///
/// Required fields: id, name, runtime, version.
/// Optional fields: metadata (default empty), model_path (optional).
/// Constraint: at least one of `metadata` (non-empty) or `model_path` must be provided.
#[derive(Debug, Default, Clone)]
pub struct ValorRighDeviceClassificationServiceBuilder {
    runtime: Option<ValorRuntimeEngine>,
    version: Option<RighVersion>,
    metadata: Option<Vec<u8>>,
    model_path: Option<PathBuf>,
}

impl ValorRighDeviceClassificationServiceBuilder {
    /// Set the runtime engine (required).
    pub fn runtime(mut self, runtime: ValorRuntimeEngine) -> Self {
        self.runtime = Some(runtime);
        self
    }

    /// Set the version (required).
    pub fn version(mut self, version: RighVersion) -> Self {
        self.version = Some(version);
        self
    }

    /// Set the metadata (optional, default empty).
    pub fn metadata<M: Into<Vec<u8>>>(mut self, metadata: M) -> Self {
        self.metadata = Some(metadata.into());
        self
    }

    /// Set the model path (optional).
    pub fn model_path<P: Into<PathBuf>>(mut self, model_path: P) -> Self {
        self.model_path = Some(model_path.into());
        self
    }

    /// Build the service, validating required fields and constraints.
    pub fn build(self) -> Result<ValorRighDeviceClassificationService> {
        let runtime = self.runtime.ok_or_else(|| anyhow!("runtime is required"))?;
        let version = self.version.ok_or_else(|| anyhow!("version is required"))?;
        let metadata = self.metadata.unwrap_or_default();
        let model_path: Option<PathBuf> = self.model_path;

        // At least one must be present: non-empty metadata or model_path
        // ensure!(
        //     !metadata.is_empty() || model_path.is_some(),
        //     "either non-empty metadata or model_path must be provided",
        // );

        Ok(ValorRighDeviceClassificationService {
            runtime,
            version,
            metadata,
            model_path,
        })
    }
}

impl ValorServiceEntity for ValorRighDeviceClassificationService {
    fn service_id(&self) -> ValorServiceId {
        ValorServiceId::righ_device_classification()
    }

    fn runtime(&self) -> ValorRuntimeEngine {
        self.runtime.clone()
    }

    fn version(&self) -> RighVersion {
        self.version.clone()
    }

    fn metadata(&self) -> Option<&[u8]> {
        Some(&self.metadata)
    }

    fn model_path(&self) -> Option<&PathBuf> {
        self.model_path.as_ref()
    }
}