use crate::marks::LineM;
use psdk_father::args::{ArgContext, PsdkArgBase, PsdkEasyArg};
use psdk_father::command::{CommandClause, PsdkTextCommand};
use psdk_father::errors::PsdkFatherResult;
use psdk_father::types::psdk_types::PsdkPrinterCommandEnumValue;
use std::sync::{Arc, Mutex};

#[derive(Clone, Debug)]
pub struct TLineOptions {
  /// 线条左上角x坐标
  pub start_x: i32,
  /// 线条左上角y坐标
  pub start_y: i32,
  /// 线条右下角x坐标
  pub end_x: i32,
  /// 线条右下角y坐标
  pub end_y: i32,
  /// 线条宽度
  pub width: i32,
  /// 实线虚线(默认实线)
  pub line: Option<LineM>,
}

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

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

impl From<(i32, i32, i32, i32, i32)> for TLine {
  fn from((start_x, start_y, end_x, end_y, width): (i32, i32, i32, i32, i32)) -> Self {
    Self::new(TLineOptions {
      start_x,
      start_y,
      end_x,
      end_y,
      width,
      line: None,
    })
  }
}

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

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

  fn clause(&self) -> PsdkFatherResult<CommandClause> {
    let mut ptc = PsdkTextCommand::with_header_format_tspl(self.header());
    let line_type = self.options.line.clone().unwrap_or(LineM::SolidLine);
    ptc
      .append(self.options.start_x)
      .append(self.options.start_y)
      .append(self.options.end_x)
      .append(self.options.end_y)
      .append(self.options.width);
    let line_type = line_type.command_value();
    if !line_type.is_empty() {
      ptc.append(line_type);
    }

    Ok(ptc.clause())
  }
}

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