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

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

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

#[derive(Clone, Debug)]
pub struct CInverseOptions {
  /// 文字反色起始x坐标
  pub x: i32,
  /// 文字反色起始y坐标
  pub y: i32,
  /// 反色文字字体
  pub font: Option<Font>,
  /// 文本内容
  pub content: String,
  /// 旋转角度(默认不旋转)
  pub rotation: Option<Rotation>,
}

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

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

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

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

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

  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);
    let rotation = self.options.rotation.clone().unwrap_or(Rotation::Rotation0);
    let x = self.options.x as i64;
    let y = self.options.y as i64;
    let font_height = font.get_height() as i64;
    let text_length = self.options.content.encode_utf16().count() as i64;

    let startx;
    let starty;
    let endx;
    let endy;
    let height;

    match rotation {
      Rotation::Rotation90 => {
        startx = x;
        starty = y - text_length * (font_height / 2);
        endx = x + font_height;
        endy = y - text_length * (font_height / 2);
        height = text_length * (font_height / 2);
      }
      Rotation::Rotation180 => {
        startx = x - text_length * (font_height / 2);
        starty = y - font_height;
        endx = x;
        endy = y - font_height;
        height = font_height;
      }
      Rotation::Rotation270 => {
        startx = x - font_height;
        starty = y;
        endx = x;
        endy = y;
        height = text_length * (font_height / 2);
      }
      _ => {
        startx = x;
        starty = y;
        endx = x + text_length * (font_height / 2);
        endy = y;
        height = font_height;
      }
    }

    ptc
      .append(startx)
      .append(starty)
      .append(endx)
      .append(endy)
      .append(height);
    Ok(ptc.clause())
  }
}

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