Documentation
use std::time::Duration;

use psdk_father::device::{ConnectedDevice, ReadOptions};

use crate::{
  connection::EmapiConnection,
  error::{EmapiError, Result},
};

pub struct ConnectedDeviceEmapiConnection<D> {
  device: D,
}

impl<D> ConnectedDeviceEmapiConnection<D>
where
  D: ConnectedDevice,
{
  pub fn new(device: D) -> Self {
    Self { device }
  }

  pub fn write(&mut self, data: &[u8]) -> Result<()> {
    EmapiConnection::write(self, data)
  }

  pub fn read(&mut self, timeout: Duration) -> Result<Vec<u8>> {
    EmapiConnection::read(self, timeout)
  }

  pub fn into_inner(self) -> D {
    self.device
  }
}

impl<D> EmapiConnection for ConnectedDeviceEmapiConnection<D>
where
  D: ConnectedDevice,
{
  fn write(&mut self, data: &[u8]) -> Result<()> {
    self
      .device
      .write(data)
      .map_err(|error| EmapiError::Connection {
        message: error.to_string(),
      })
  }

  fn read(&mut self, timeout: Duration) -> Result<Vec<u8>> {
    let data = self
      .device
      .read(Some(ReadOptions {
        timeout: timeout.as_millis().min(u128::from(u32::MAX)) as u32,
      }))
      .map_err(|error| EmapiError::Connection {
        message: error.to_string(),
      })?;
    if data.is_empty() {
      return Err(EmapiError::Timeout {
        message: "device read returned no data".to_string(),
      });
    }
    Ok(data)
  }
}