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

use crate::args::{CBold, CBoldOptions, CMag, CMagOptions, CUnderLine, CUnderLineOptions};
use psdk_father::{
  args::{ArgContext, PsdkArgBase, PsdkEasyArg},
  command::{CommandClause, PsdkTextCommand},
  errors::PsdkFatherResult,
  types::psdk_types::PsdkPrinterCommandEnumValue,
};

use crate::marks::{Font, Rotation};

#[derive(Clone, Debug)]
pub struct CTextOptions {
  /// 字体(默认TSS16)
  pub font: Option<Font>,
  /// 文字起始x坐标
  pub x: i32,
  /// 文字起始y坐标
  pub y: i32,
  /// 打印的文本内容
  pub content: String,
  /// 是否加粗(默认不加粗)
  pub bold: Option<bool>,
  /// 是否加下划线(默认不加下划线)
  pub underline: Option<bool>,
  /// 是否字体倍数放大(默认不放大)
  pub mag: Option<bool>,
  /// 文字旋转角度(默认不旋转)
  pub rotation: Option<Rotation>,
}

#[derive(Clone, Debug)]
pub struct CText {
  options: CTextOptions,
  ctx: Arc<Mutex<ArgContext>>,
}

impl CText {
  pub fn new(options: CTextOptions) -> Self {
    Self {
      options,
      ctx: Default::default(),
    }
  }
}

impl<T: Into<String>> From<(i32, i32, T)> for CText {
  fn from((x, y, content): (i32, i32, T)) -> Self {
    Self::new(CTextOptions {
      font: None,
      x,
      y,
      content: content.into(),
      bold: None,
      underline: None,
      mag: None,
      rotation: None,
    })
  }
}

impl PsdkEasyArg<String> for CText {
  fn context(&self) -> Arc<Mutex<ArgContext>> {
    self.ctx.clone()
  }
}

impl PsdkArgBase<String> for CText {
  fn header(&self) -> String {
    let rotation = self.options.rotation.clone().unwrap_or(Rotation::Rotation0);
    format!("T{}", rotation.command_value())
  }

  fn clause(&self) -> PsdkFatherResult<CommandClause> {
    let mut ptc = PsdkTextCommand::with_header_format_cpcl(self.header());
    let font = self.options.font.clone().unwrap_or(Font::Tss16);
    if let Some(bold) = self.options.bold {
      let cbold = CBold::new(CBoldOptions { enable: bold });
      self.prepend(&cbold).unwrap();
    }
    if let Some(underline) = self.options.underline {
      let cunder_line = CUnderLine::new(CUnderLineOptions { enable: underline });
      self.prepend(&cunder_line).unwrap();
    }
    if self.options.mag.is_some() {
      let cmag = CMag::new(CMagOptions {
        font: Some(font.clone()),
      });
      self.prepend(&cmag).unwrap();
    }
    ptc
      .append(font.get_family())
      .append(font.get_size())
      .append(self.options.x)
      .append(self.options.y)
      .append(&self.options.content);
    Ok(ptc.clause())
  }
}

psdk_father::impl_psdk_arg_to_easy_arg!(String, CText, true);