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

use super::TImagePixels;
use crate::marks::TImageMode;
use psdk_extension::imagep::{ThresholdEdgeDitherDepth, ThresholdEdgeDitherMode};

#[derive(Clone, Debug)]
pub struct TImageBytesOptions {
  // 图片起始x坐标
  pub x: i32,
  // 图片起始y坐标
  pub y: i32,
  // 图片数据
  pub bytes: Vec<u8>,
  // 是否压缩
  pub compress: bool,
  // 是否反色
  pub reverse: bool,
  // 二值化0-255(默认190)
  pub gray_threshold: Option<i32>,
  // 平滑权重(默认0)
  pub smooth_weight: i32,
  // 边缘抖动模式
  pub edge_dither_mode: Option<ThresholdEdgeDitherMode>,
  // 边缘抖动深度
  pub edge_dither_depth: ThresholdEdgeDitherDepth,
  // 图片绘制模式
  pub image_mode: TImageMode,
}

#[derive(Clone, Debug)]
pub struct TImageBytes {
  image_pixels: TImagePixels,
}

impl TImageBytes {
  pub fn new(options: TImageBytesOptions) -> PsdkFatherResult<Self> {
    let pixmap =
      Pixmap::decode_png(&options.bytes).map_err(|e| PsdkFatherError::Image(format!("{:?}", e)))?;
    let width = pixmap.width();
    let height = pixmap.height();
    Ok(Self {
      image_pixels: TImagePixels::new(super::TImagePixelsOptions {
        x: options.x,
        y: options.y,
        pixels: pixmap.take(),
        width,
        height,
        compress: options.compress,
        reverse: options.reverse,
        gray_threshold: options.gray_threshold,
        smooth_weight: options.smooth_weight,
        edge_dither_mode: options.edge_dither_mode,
        edge_dither_depth: options.edge_dither_depth,
        image_mode: options.image_mode,
      }),
    })
  }
}

impl TryFrom<(i32, i32, Vec<u8>)> for TImageBytes {
  type Error = PsdkFatherError;

  fn try_from((x, y, bytes): (i32, i32, Vec<u8>)) -> Result<Self, Self::Error> {
    Self::new(TImageBytesOptions {
      x,
      y,
      bytes,
      compress: false,
      reverse: false,
      gray_threshold: None,
      smooth_weight: 0,
      edge_dither_mode: None,
      edge_dither_depth: Default::default(),
      image_mode: TImageMode::Overwrite,
    })
  }
}

impl PsdkEasyArg<String> for TImageBytes {
  fn context(&self) -> Arc<Mutex<ArgContext>> {
    self.image_pixels.context()
  }
}

impl PsdkArgBase<String> for TImageBytes {
  fn header(&self) -> String {
    self.image_pixels.header()
  }

  fn clause(&self) -> PsdkFatherResult<CommandClause> {
    self.image_pixels.clause()
  }
}

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