Documentation
use std::sync::{Arc, Mutex};

use crate::args::{
  CBar, CBatteryVolume, CBold, CBoldOptions, CBox, CFeed, CForm, CImagePixels, CInverse, CLine,
  CMag, CModel, CPage, CPageHeight, CPageMode, CPageWidth, CPrint, CQRCode, CStatus, CText,
  CUnderLine, CUnderLineOptions, CVersion, CWaterMark, CSN,
};
#[cfg(feature = "image-plus")]
use crate::args::{CImageBytes, CTextCanvas};
use psdk_father::{
  command::Commander, device::ConnectedDevice, errors::PsdkFatherResult, psdk::Psdk,
  types::psdk_types::Lifecycle,
};

#[cfg(feature = "image-plus")]
pub trait IntoCpclImageArg<T> {
  fn into_cpcl_image_arg(self) -> PsdkFatherResult<T>;
}

#[cfg(feature = "image-plus")]
impl IntoCpclImageArg<CImageBytes> for CImageBytes {
  fn into_cpcl_image_arg(self) -> PsdkFatherResult<CImageBytes> {
    Ok(self)
  }
}

#[cfg(feature = "image-plus")]
impl IntoCpclImageArg<CImageBytes> for (i32, i32, Vec<u8>) {
  fn into_cpcl_image_arg(self) -> PsdkFatherResult<CImageBytes> {
    CImageBytes::try_from(self)
  }
}

#[cfg(feature = "image-plus")]
impl IntoCpclImageArg<CTextCanvas> for CTextCanvas {
  fn into_cpcl_image_arg(self) -> PsdkFatherResult<CTextCanvas> {
    Ok(self)
  }
}

#[cfg(feature = "image-plus")]
impl IntoCpclImageArg<CTextCanvas> for (i32, i32, Vec<u8>) {
  fn into_cpcl_image_arg(self) -> PsdkFatherResult<CTextCanvas> {
    CTextCanvas::try_from(self)
  }
}

pub struct BaseCpcl {
  lifecycle: Lifecycle,
  commander: Commander,
}

impl BaseCpcl {
  pub fn new(lifecycle: Lifecycle) -> Self {
    Self {
      lifecycle,
      commander: Commander::new(),
    }
  }

  pub fn with_lifecycle(lifecycle: Lifecycle) -> Self {
    Self::new(lifecycle)
  }

  pub fn with_connected_device(connected_device: Arc<Mutex<dyn ConnectedDevice>>) -> Self {
    Self::with_lifecycle(Lifecycle::simple(connected_device))
  }
}

impl Psdk for BaseCpcl {
  fn commander(&mut self) -> &mut Commander {
    &mut self.commander
  }

  fn connected_device(&self) -> Arc<Mutex<dyn ConnectedDevice>> {
    self.lifecycle.connected_device.clone()
  }
}

impl BaseCpcl {
  ///一维码
  pub fn bar(&mut self, arg: impl Into<CBar>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  ///画矩形边框
  pub fn box_(&mut self, arg: impl Into<CBox>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  ///加粗
  pub fn bold(&mut self, arg: bool) -> PsdkFatherResult<&mut Self> {
    self.push_arg(CBold::new(CBoldOptions { enable: arg }))?;
    Ok(self)
  }

  ///定位到标签(可以放在print指令之后调用)
  pub fn form(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(CForm::new())?;
    Ok(self)
  }

  ///定位到标签
  pub fn feed(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(CFeed::new())?;
    Ok(self)
  }

  /// 打印图片 (bytes)
  #[cfg(feature = "image-plus")]
  pub fn image_bytes(
    &mut self,
    arg: impl IntoCpclImageArg<CImageBytes>,
  ) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into_cpcl_image_arg()?)?;
    Ok(self)
  }

  /// 打印图片 (pixels)
  pub fn image(&mut self, arg: impl Into<CImagePixels>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 打印图片 (pixels)
  pub fn image_pixels(&mut self, arg: impl Into<CImagePixels>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 文字反白
  pub fn inverse(&mut self, arg: impl Into<CInverse>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 画线(能画斜线)
  pub fn line(&mut self, arg: impl Into<CLine>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 字体放大
  pub fn mag(&mut self, arg: impl Into<CMag>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 打印模式
  pub fn page_mode(&mut self, arg: impl Into<CPageMode>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 创建打印页面大小
  pub fn page(&mut self, arg: impl Into<CPage>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 创建打印页面高度
  pub fn page_height(&mut self, arg: impl Into<CPageHeight>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 创建打印页面宽度
  pub fn page_width(&mut self, arg: impl Into<CPageWidth>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 打印
  pub fn print(&mut self, arg: impl Into<CPrint>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 打印
  pub fn print_default(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(CPrint::default())?;
    Ok(self)
  }

  /// 打印二维码
  pub fn qrcode(&mut self, arg: impl Into<CQRCode>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 打印文本
  pub fn text(&mut self, arg: impl Into<CText>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 图片文本
  #[cfg(feature = "image-plus")]
  pub fn text_canvas(
    &mut self,
    arg: impl IntoCpclImageArg<CTextCanvas>,
  ) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into_cpcl_image_arg()?)?;
    Ok(self)
  }

  ///下划线
  pub fn underline(&mut self, arg: bool) -> PsdkFatherResult<&mut Self> {
    self.push_arg(CUnderLine::new(CUnderLineOptions { enable: arg }))?;
    Ok(self)
  }

  /// 水印
  pub fn water_mark(&mut self, arg: impl Into<CWaterMark>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  ///查询打印机状态
  pub fn status(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(CStatus::new())?;
    Ok(self)
  }

  ///查询打印机SN
  pub fn sn(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(CSN::new())?;
    Ok(self)
  }

  ///查询打印机型号
  pub fn model(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(CModel::new())?;
    Ok(self)
  }

  ///查询固件版本
  pub fn version(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(CVersion::new())?;
    Ok(self)
  }

  ///查询电量
  pub fn battery_volume(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(CBatteryVolume::new())?;
    Ok(self)
  }
}