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

#[derive(Clone, Debug)]
pub struct TBlineOptions {
  pub height: Option<i32>,
  pub offset: Option<i32>,
}

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

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

impl Default for TBline {
  fn default() -> Self {
    Self::new(TBlineOptions {
      height: None,
      offset: None,
    })
  }
}

impl From<(i32, i32)> for TBline {
  fn from((height, offset): (i32, i32)) -> Self {
    Self::new(TBlineOptions {
      height: Some(height),
      offset: Some(offset),
    })
  }
}

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

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

  fn clause(&self) -> PsdkFatherResult<CommandClause> {
    let mut ptc = PsdkTextCommand::with_header_format_tspl(self.header());
    let height = self.options.height.unwrap_or(3);
    let offset = self.options.offset.unwrap_or(0);
    ptc.append(height.to_string() + " mm");
    ptc.append(offset.to_string() + " mm");

    Ok(ptc.clause())
  }
}

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