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

use psdk_father::{
  command::Commander, device::ConnectedDevice, errors::PsdkFatherResult, psdk::Psdk,
  types::psdk_types::Lifecycle,
};

#[cfg(feature = "image-plus")]
use crate::args::TImageBytes;
use crate::args::{
  TAutoDot, TBar, TBarCode, TBatteryVolume, TBlack, TBline, TBox, TCircle, TCleanBmpFlash,
  TCleanBmpFlashOptions, TCls, TContinuous, TCut, TCutOptions, TDensity, TDensityOptions,
  TDirection, TDmatrix, TEllipse, TGBKCode, TGap, TGapOptions, TGetRibbonEnd, TImagePixels, TLabel,
  TLearnPaperGap, TLine, TMddle, TModels, TOffset, TPage, TPeel, TPrint, TPutImage, TQRCode,
  TReadHardwareVersion, TReadState, TRed, TRedOptions, TReference, TReferenceOptions,
  TResetFactory, TReverse, TRibbon, TSNs, TSelfTest, TSetRibbonEnd, TSetRibbonEndOptions, TShift,
  TSpeed, TSpeedOptions, TStatus, TTear, TText, TTextBox, TUTF8Code, TVersion, TVersions, TSN,
};

#[cfg(feature = "image-plus")]
pub trait IntoTsplImageBytesArg {
  fn into_tspl_image_bytes_arg(self) -> PsdkFatherResult<TImageBytes>;
}

#[cfg(feature = "image-plus")]
impl IntoTsplImageBytesArg for TImageBytes {
  fn into_tspl_image_bytes_arg(self) -> PsdkFatherResult<TImageBytes> {
    Ok(self)
  }
}

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

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

impl BaseTspl {
  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 BaseTspl {
  fn commander(&mut self) -> &mut Commander {
    &mut self.commander
  }

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

impl BaseTspl {
  pub fn auto_dot(&mut self, arg: impl Into<TAutoDot>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 画线(只能画横竖线)
  pub fn bar(&mut self, arg: impl Into<TBar>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

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

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

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

  /// 黑标纸打印
  pub fn bline_default(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TBline::default())?;
    Ok(self)
  }

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

  /// 画圆
  pub fn circle(&mut self, arg: impl Into<TCircle>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 画椭圆
  pub fn ellipse(&mut self, arg: impl Into<TEllipse>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 清除位图
  pub fn clean_flash(&mut self, index: i32) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TCleanBmpFlash::new(TCleanBmpFlashOptions { index }))?;
    Ok(self)
  }

  /// 清除页面缓冲区
  pub fn cls(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TCls::new())?;
    Ok(self)
  }

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

  /// 连续纸打印
  pub fn continuous_default(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TContinuous::default())?;
    Ok(self)
  }

  /// 使能切刀
  pub fn cut(&mut self, enable: bool) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TCut::new(TCutOptions { enable }))?;
    Ok(self)
  }

  /// 设置浓度(0-15)
  pub fn density(&mut self, density: i32) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TDensity::new(TDensityOptions { density }))?;
    Ok(self)
  }

  /// 设置打印方向
  pub fn direction(&mut self, arg: impl Into<TDirection>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

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

  /// 定位缝隙
  pub fn gap(&mut self, enable: bool) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TGap::new(TGapOptions { enable }))?;
    Ok(self)
  }

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

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

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

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

  /// 标签纸打印
  pub fn label_default(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TLabel::default())?;
    Ok(self)
  }

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

  pub fn mddle(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TMddle::new())?;
    Ok(self)
  }

  /// 进纸
  pub fn offset(&mut self, arg: impl Into<TOffset>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 进纸
  pub fn offset_default(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TOffset::default())?;
    Ok(self)
  }

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

  /// 是否剥去
  pub fn peel(&mut self, arg: impl Into<TPeel>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

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

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

  /// 打印打印机里缓存的图片
  pub fn put_image(&mut self, arg: impl Into<TPutImage>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

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

  /// 查询状态
  pub fn state(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TReadState::new())?;
    Ok(self)
  }

  /// 红色打印(0-15)
  pub fn set_red(&mut self, density: i32) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TRed::new(TRedOptions { density }))?;
    Ok(self)
  }

  /// 黑色打印
  pub fn set_black(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TBlack::new())?;
    Ok(self)
  }

  /// 打印自检页
  pub fn self_test(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TSelfTest::new())?;
    Ok(self)
  }

  /// 设置碳尾开关
  pub fn set_ribbon_end(&mut self, enable: bool) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TSetRibbonEnd::new(TSetRibbonEndOptions { enable }))?;
    Ok(self)
  }

  /// 获取当前碳尾开关(0关，1开)
  pub fn get_ribbon_end(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TGetRibbonEnd::new())?;
    Ok(self)
  }

  /// 热转印的版本号获取
  pub fn versions(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TVersions::new())?;
    Ok(self)
  }

  /// 热转印的型号获取
  pub fn models(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TModels::new())?;
    Ok(self)
  }

  /// 热转印的sn获取
  pub fn sns(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TSNs::new())?;
    Ok(self)
  }

  /// 打印机设置成gbk编码
  pub fn set_gbk_code(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TGBKCode::new())?;
    Ok(self)
  }

  /// 打印机设置成utf-8编码
  pub fn set_utf8_code(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TUTF8Code::new())?;
    Ok(self)
  }

  /// 学习纸张（间隙检测）
  pub fn learn_paper_gap(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TLearnPaperGap::new())?;
    Ok(self)
  }

  /// 读取硬件版本
  pub fn read_hardware_version(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TReadHardwareVersion::new())?;
    Ok(self)
  }

  /// 恢复出厂设置
  pub fn reset_to_factory(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TResetFactory::new())?;
    Ok(self)
  }

  /// 相对偏移
  pub fn reference(&mut self, horizontal: i32, vertical: i32) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TReference::new(TReferenceOptions {
      horizontal: Option::from(horizontal),
      vertical: Option::from(vertical),
    }))?;
    Ok(self)
  }

  /// 相对偏移
  pub fn reference_default(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TReference::default())?;
    Ok(self)
  }

  pub fn reference_arg(&mut self, arg: impl Into<TReference>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  ///  反色
  pub fn reverse(&mut self, arg: impl Into<TReverse>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 热敏模式
  pub fn ribbon(&mut self, arg: impl Into<TRibbon>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 垂直偏移
  pub fn shift(&mut self, arg: impl Into<TShift>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

  /// 垂直偏移
  pub fn shift_default(&mut self) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TShift::default())?;
    Ok(self)
  }

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

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

  /// 设置速度
  pub fn speed(&mut self, speed: i32) -> PsdkFatherResult<&mut Self> {
    self.push_arg(TSpeed::new(TSpeedOptions { speed }))?;
    Ok(self)
  }

  /// 是否撕去
  pub fn tear(&mut self, arg: impl Into<TTear>) -> PsdkFatherResult<&mut Self> {
    self.push_arg(arg.into())?;
    Ok(self)
  }

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

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

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