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

use psdk_father::{
  args::{ArgContext, PsdkArgBase, PsdkEasyArg},
  command::{CommandClause, PsdkTextCommand},
  errors::PsdkFatherResult,
};

#[derive(Clone, Debug)]
pub struct CBoxOptions {
  /// 矩形框框线条宽度
  pub line_width: i32,
  /// 矩形框左上角x坐标
  pub top_left_x: i32,
  /// 矩形框左上角y坐标
  pub top_left_y: i32,
  /// 矩形框右下角x坐标
  pub bottom_right_x: i32,
  /// 矩形框右下角y坐标
  pub bottom_right_y: i32,
}

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

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

impl From<(i32, i32, i32, i32, i32)> for CBox {
  fn from(
    (line_width, top_left_x, top_left_y, bottom_right_x, bottom_right_y): (i32, i32, i32, i32, i32),
  ) -> Self {
    Self::new(CBoxOptions {
      line_width,
      top_left_x,
      top_left_y,
      bottom_right_x,
      bottom_right_y,
    })
  }
}

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

impl PsdkArgBase<String> for CBox {
  fn header(&self) -> String {
    "BOX".to_string()
  }

  fn clause(&self) -> PsdkFatherResult<CommandClause> {
    let mut ptc = PsdkTextCommand::with_header_format_cpcl(self.header());
    let top_left_x = self.options.top_left_x.min(575);
    let bottom_right_x = self.options.bottom_right_x.min(575);
    ptc
      .append(top_left_x)
      .append(self.options.top_left_y)
      .append(bottom_right_x)
      .append(self.options.bottom_right_y)
      .append(self.options.line_width);
    Ok(ptc.clause())
  }
}

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