include!(concat!(env!("OUT_DIR"), "/opamp.proto.rs"));
use async_trait::async_trait;
use std::{error::Error, fmt, any::Any};

#[derive(Debug)]
pub struct OpAMPClientError {
    pub code: u32,
    pub details: String,
}

impl OpAMPClientError {
    pub fn new(code: u32, msg: &str) -> OpAMPClientError {
        OpAMPClientError {
            code,
            details: format!("Service Error <{}> : {}", &code, &msg),
        }
    }

    pub fn code(&self) -> u32 {
        self.code
    }
}

impl fmt::Display for OpAMPClientError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.details)
    }
}

impl Error for OpAMPClientError {
    fn description(&self) -> &str {
        &self.details
    }
}

pub type ClientBuffer = Vec<u8>;

#[async_trait]
pub trait Client {
    fn process(&mut self, current_state: &dyn Any) -> bool;
    async fn connect(&mut self) -> Result<(), OpAMPClientError>;
    async fn send(&mut self, buf: &ClientBuffer) -> Result<(), OpAMPClientError>;
}
