Documentation
#![allow(deprecated)]
use std::io::Cursor;

use crate::{AnyRes, Result};
use image::io::Reader;
pub use image::{ColorType, DynamicImage, GenericImageView, ImageFormat};

/// #枚举图像数据的来源
/// # Example
/// ```rust
/// use e_utils::images::ImageSource;
/// fn test() -> Result<()> {
///   let file_image = ImageSource::File("D:\\1.jpeg".to_string()).to_image()?;
///   let (width, height) = file_image.dimensions();
///   println!("Image dimensions (from file): {} x {}", width, height);
///   let url_image = ImageSource::Url(
///     "http://q5.itc.cn/q_70/images03/20240222/d442108f65694b5081b0e793208a704c.jpeg".to_string(),
///   )
///   .to_image()?;
///   let (width, height) = file_image.dimensions();
///   println!("Image dimensions (from Url): {} x {}", width, height);
///   url_image.save("D:\\url.jpeg")?;
///   Ok(())
/// }
/// fn test2() -> Result<()>{
///   // 从内存中获取数据
///   let image = unsafe { ImageSource::from_raw_parts(pic_buf_ptr, (*size_returned) as usize) }
///     .to_image()
///     .to_tauri()?;
///   // 获取图片数据
///   let base64 = ImageSource::image_to_base64(&image);
///   let bytes = ImageSource::image_into_bytes(image.clone());
///   let (ptr, len) = ImageSource::image_to_ptr(image).to_tauri()?;
///   let image = unsafe { ImageSource::from_raw_parts(ptr, len) };
///   Ok(())
/// }
/// ```
#[derive(Debug)]
pub enum ImageSource<'a> {
  /// 从文件加载图像,传入文件路径
  File(String),
  /// 从内存加载图像,传入图像数据的字节向量
  Memory(&'a [u8]),
  /// 从URL加载图像,传入URL地址
  Url(String),
  /// 从数据库加载图像,传入图像ID(假设)
  Database(u64),
  /// 从网络流加载图像,传入字节数据流
  NetworkStream(Vec<u8>),
}

impl<'a> ImageSource<'a> {
  /// 输出图像
  pub fn to_image(self) -> Result<DynamicImage> {
    Ok(match self {
      ImageSource::File(file_path) => image::open(file_path).map_err(|e| e.to_string())?,
      ImageSource::Memory(image_data) => {
        image::load_from_memory(&image_data).map_err(|e| e.to_string())?
      }
      ImageSource::Url(_url) => {
        #[cfg(not(feature = "http-blocking"))]
        return Err("Need add feature = http-blocking".into());
        #[cfg(feature = "http-blocking")]
        {
          let response = reqwest::blocking::get(&_url).map_err(|e| e.to_string())?;
          let image_data = response.bytes().map_err(|e| e.to_string())?.to_vec();
          image::load_from_memory(&image_data).map_err(|e| e.to_string())?
        }
      }
      ImageSource::Database(_image_id) => {
        // 根据图像ID从数据库检索图像数据
        // 这里假设您有一个名为 load_from_database 的函数来执行此操作
        // let image_data = load_from_database(image_id);
        // image::load_from_memory(&image_data).expect("Failed to load image from database")
        return Err("Database image loading is not implemented yet".into());
      }
      ImageSource::NetworkStream(bytes) => {
        // 从网络流加载图像数据
        let reader = std::io::Cursor::new(bytes);
        Reader::new(reader)
          .with_guessed_format().any()?
          .decode()
          .map_err(|e| e.to_string())?
      }
    })
  }

  /// 从指针获取数据
  pub const unsafe fn from_raw_parts<T>(buf_ptr: *const T, len: usize) -> &'a [T] {
    std::slice::from_raw_parts(buf_ptr, len)
  }
  /// 从指针获取数据
  pub unsafe fn from_raw_parts_image<T>(buf_ptr: *const T, len: usize) -> Self {
    Self::Memory(Self::from_raw_parts(buf_ptr as *const u8, len))
  }
  /// 从指针获取数据
  pub unsafe fn from_raw_parts_reader<T>(
    buf_ptr: *const T,
    len: usize,
  ) -> Result<Reader<Cursor<&'a [u8]>>> {
    let x = Reader::new(std::io::Cursor::new(Self::from_raw_parts(
      buf_ptr as *const u8,
      len,
    )))
    .with_guessed_format().any()?;
    Ok(x)
  }
  /// 从指针获取数据
  #[cfg(feature = "base64")]
  pub unsafe fn from_raw_parts_base64<T>(buf_ptr: *const T, len: usize) -> Result<String> {
    let reader = Self::from_raw_parts_reader(buf_ptr, len)?;
    let iformat = reader.format().res()?;
    let image = reader.decode().map_err(|e| e.to_string())?;
    Self::image_to_base64(&image, iformat)
  }
  /// 转成指针和长度
  pub fn to_ptr(self) -> Result<(*const u8, usize)> {
    let image = self.to_image()?;
    Self::image_to_ptr(image)
  }

  /// 转数据
  pub fn image_write_bytes(
    image: &DynamicImage,
    iformat: image::ImageFormat,
  ) -> Result<Cursor<Vec<u8>>> {
    // 创建一个内存缓冲区
    let mut cursor = Cursor::new(Vec::new());
    image
      .write_to(&mut cursor, iformat)
      .map_err(|e| e.to_string())?;
    Ok(cursor)
  }

  /// 转Base64
  #[cfg(feature = "base64")]
  pub fn to_base64(self, iformat: ImageFormat) -> Result<String> {
    let image = self.to_image()?;
    Self::image_to_base64(&image, iformat)
  }

  /// 转base64
  #[cfg(feature = "base64")]
  pub fn image_to_base64(image: &DynamicImage, iformat: ImageFormat) -> Result<String> {
    Ok(crate::algorithm::base64::encode(
      Self::image_write_bytes(image, iformat)?.into_inner(),
    ))
  }

  /// 转成指针和长度
  pub fn image_to_ptr(image: DynamicImage) -> Result<(*const u8, usize)> {
    // 获取图像尺寸
    let (width, height) = image.dimensions();
    // 获取图像颜色类型
    let color_type = image.color();
    // 获取图像像素数据的指针
    // 根据颜色类型确定每个像素的大小
    let (ptr, pixel_size) = match color_type {
      // RGB 图像,每个像素需要3个字节
      ColorType::Rgb8 => (image.into_rgb8().as_ptr(), 3),
      // RGBA 图像,每个像素需要4个字节
      ColorType::Rgba8 => (image.into_rgba8().as_ptr(), 4),
      _ => return Err("ColorType未知类型".into()),
    };
    // 计算图像像素数据的总大小
    let total_size = (width * height) as usize * pixel_size;
    Ok((ptr, total_size))
  }
}