package org.example.Utils;

import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Iterator;

/**
 * 图片处理工具类
 * 功能描述：图片格式转换、缩放、旋转、合并等操作
 * 版本：1.0.0.0
 */
public class ImageUtil {

    /**
     * 图片深度枚举
     */
    public enum ImgDeep {
        D8,
        D32
    }

    /**
     * 格式化图片（转换格式、调整大小、设置深度）
     *
     * @param path     源图片路径
     * @param savePath 保存路径
     * @param format   目标图片格式（如"jpg"、"png"等）
     * @param deep     图片深度
     * @param nwidth   目标宽度（0表示不调整）
     * @param nheight  目标高度（0表示不调整）
     * @throws IOException 图片处理异常
     */
    public static void format(String path, String savePath, String format, ImgDeep deep, int nwidth, int nheight) throws IOException {
        BufferedImage srcImage;

        // 根据指定尺寸调整图片
        if (nwidth > 0 && nheight > 0) {
            srcImage = reSize(path, nwidth, nheight);
        } else {
            srcImage = ImageIO.read(new File(path));
        }

        // 处理8位深度图片（通过GIF格式中转）
        if (deep == ImgDeep.D8) {
            String tempPath = savePath + ".temp";
            format(srcImage, tempPath, "gif"); // GIF为8位索引色
            format(new File(tempPath), savePath, format);
            new File(tempPath).delete();
            return;
        }

        // 直接保存图片
        format(srcImage, savePath, format);
    }

    /**
     * 重载方法，使用默认深度D32
     */
    public static void format(String path, String savePath, String format) throws IOException {
        format(path, savePath, format, ImgDeep.D32, 0, 0);
    }

    /**
     * 调整图片大小（保持比例）
     *
     * @param path    源图片路径
     * @param nwidth  目标宽度
     * @param nheight 目标高度
     * @return 调整后的图片
     * @throws IOException 图片读取/处理异常
     */
    public static BufferedImage reSize(String path, int nwidth, int nheight) throws IOException {
        BufferedImage source = ImageIO.read(new File(path));
        int sW = 0, sH = 0;
        int originalWidth = source.getWidth();
        int originalHeight = source.getHeight();

        // 计算缩放后的尺寸（保持比例）
        if (nwidth > 0 || nheight > 0) {
            if ((long) originalWidth * nheight > (long) originalHeight * nwidth) {
                sW = nwidth;
                sH = (nwidth * originalHeight) / originalWidth;
            } else {
                sH = nheight;
                sW = (originalWidth * nheight) / originalHeight;
            }
        } else {
            sW = originalWidth;
            sH = originalHeight;
        }

        // 创建缩放后的图片
        BufferedImage resized = new BufferedImage(sW, sH, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = resized.createGraphics();

        // 设置高质量缩放参数
        g.setComposite(AlphaComposite.Src);
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        g.drawImage(source, 0, 0, sW, sH, 0, 0, originalWidth, originalHeight, null);
        g.dispose();


        return resized;
    }

    /**
     * 将BufferedImage保存为指定格式的图片文件
     *
     * @param bmp      图片对象
     * @param filename 保存路径
     * @param format   图片格式
     * @throws IOException 保存异常
     */
    public static void format(BufferedImage bmp, String filename, String format) throws IOException {
        File outputFile = new File(filename);
        ImageWriter writer = getImageWriter(format);
        if (writer == null) {
            throw new IllegalArgumentException("不支持的图片格式: " + format);
        }

        // 设置压缩质量
        ImageWriteParam param = writer.getDefaultWriteParam();
        if (param.canWriteCompressed()) {
            param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            param.setCompressionQuality(1.0f); // 最高质量
        }

        try (ImageOutputStream ios = ImageIO.createImageOutputStream(outputFile)) {
            writer.setOutput(ios);
            writer.write(null, new javax.imageio.IIOImage(bmp, null, null), param);
        } finally {
            writer.dispose();
            bmp.flush();
        }
    }

    /**
     * 将图片文件转换格式
     *
     * @param sourceFile 源文件
     * @param targetPath 目标路径
     * @param format     目标格式
     * @throws IOException 处理异常
     */
    public static void format(File sourceFile, String targetPath, String format) throws IOException {
        BufferedImage image = ImageIO.read(sourceFile);
        format(image, targetPath, format);
    }

    /**
     * 获取指定格式的ImageWriter
     *
     * @param format 图片格式（如"jpg"、"png"）
     * @return ImageWriter对象
     */
    private static ImageWriter getImageWriter(String format) {
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(format);
        if (writers.hasNext()) {
            return writers.next();
        }
        return null;
    }

    /**
     * 判断文件是否为图片
     *
     * @param filePath 文件路径
     * @return 是否为图片
     */
    public static boolean isImg(String filePath) {
        if (filePath == null || filePath.isEmpty()) {
            return false;
        }

        String[] imgExtensions = {".jpg", ".jpeg", ".jpe", ".png", ".gif", ".bmp", ".tif"};
        String extension = getFileExtension(filePath).toLowerCase();
        for (String ext : imgExtensions) {
            if (ext.equals(extension)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取文件扩展名（带点）
     */
    private static String getFileExtension(String filePath) {
        int lastDotIndex = filePath.lastIndexOf('.');
        if (lastDotIndex == -1) {
            return "";
        }
        return filePath.substring(lastDotIndex);
    }

    /**
     * 将BufferedImage转换为字节数组
     *
     * @param bitmap 图片对象
     * @return 字节数组
     * @throws IOException 转换异常
     */
    public static byte[] bitmapToBytes(BufferedImage bitmap) throws IOException {
        try (ByteArrayOutputStream ms = new ByteArrayOutputStream()) {
            ImageIO.write(bitmap, "png", ms); // 使用PNG格式避免压缩损失
            return ms.toByteArray();
        }
    }

    /**
     * 将字节数组转换为输入流
     *
     * @param bytes 字节数组
     * @return 输入流
     */
    public static InputStream bytesToStream(byte[] bytes) {
        return new ByteArrayInputStream(bytes);
    }

    /**
     * 根据图片EXIF信息旋转图片（修复拍照方向问题）
     *
     * @param path 图片路径
     * @throws IOException 处理异常
     */
    public static void translateImageByTag(String path) throws IOException {
        if (!isImg(path)) {
            return;
        }

        File file = new File(path);
        BufferedImage bmp = ImageIO.read(file);
        rotating(bmp, path);
        bmp.flush();
    }

    /**
     * 旋转图片并保存
     *
     * @param img      图片对象
     * @param fullname 保存路径
     * @throws IOException 保存异常
     */
    private static void rotating(BufferedImage img, String fullname) throws IOException {
        // 获取EXIF方向信息（274是方向标签ID）
        int orientation = 0;
        try {
            // 尝试读取方向信息（Java内置API不直接支持EXIF，此处为简化实现）
            // 实际项目中可使用metadata-extractor等库获取EXIF信息
            // 参考: https://github.com/drewnoakes/metadata-extractor
            orientation = getExifOrientation(img);
        } catch (Exception e) {
            // 忽略获取方向信息失败的情况
        }

        BufferedImage rotatedImage = img;
        int width = img.getWidth();
        int height = img.getHeight();

        // 根据方向信息旋转图片
        switch (orientation) {
            case 2:
                rotatedImage = rotateFlip(img, RotationType.FLIP_HORIZONTAL);
                break;
            case 3:
                rotatedImage = rotateFlip(img, RotationType.ROTATE_180);
                break;
            case 4:
                rotatedImage = rotateFlip(img, RotationType.FLIP_VERTICAL);
                break;
            case 5:
                rotatedImage = rotateFlip(img, RotationType.ROTATE_90_FLIP_HORIZONTAL);
                break;
            case 6:
                rotatedImage = rotateFlip(img, RotationType.ROTATE_90);
                width = img.getHeight();
                height = img.getWidth();
                break;
            case 7:
                rotatedImage = rotateFlip(img, RotationType.ROTATE_270_FLIP_HORIZONTAL);
                break;
            case 8:
                rotatedImage = rotateFlip(img, RotationType.ROTATE_270);
                width = img.getHeight();
                height = img.getWidth();
                break;
            default:
                return; // 无需旋转
        }

        // 保存旋转后的图片
        String format = getFileExtension(fullname).substring(1); // 去除点号
        format(rotatedImage, fullname, format);
        rotatedImage.flush();
    }

    /**
     * 旋转或翻转图片
     */
    private static BufferedImage rotateFlip(BufferedImage img, RotationType type) {
        int width = img.getWidth();
        int height = img.getHeight();
        BufferedImage result;
        Graphics2D g;

        switch (type) {
            case ROTATE_90:
                result = new BufferedImage(height, width, img.getType());
                g = result.createGraphics();
                g.rotate(Math.PI / 2, height / 2.0, height / 2.0);
                g.drawImage(img, 0, -width, null);
                break;
            case ROTATE_180:
                result = new BufferedImage(width, height, img.getType());
                g = result.createGraphics();
                g.rotate(Math.PI, width / 2.0, height / 2.0);
                g.drawImage(img, -width, -height, null);
                break;
            case ROTATE_270:
                result = new BufferedImage(height, width, img.getType());
                g = result.createGraphics();
                g.rotate(Math.PI * 3 / 2, width / 2.0, width / 2.0);
                g.drawImage(img, -height, 0, null);
                break;
            case FLIP_HORIZONTAL:
                result = new BufferedImage(width, height, img.getType());
                g = result.createGraphics();
                g.drawImage(img, width, 0, -width, height, null);
                break;
            case FLIP_VERTICAL:
                result = new BufferedImage(width, height, img.getType());
                g = result.createGraphics();
                g.drawImage(img, 0, height, width, -height, null);
                break;
            case ROTATE_90_FLIP_HORIZONTAL:
                result = rotateFlip(rotateFlip(img, RotationType.ROTATE_90), RotationType.FLIP_HORIZONTAL);
                return result;
            case ROTATE_270_FLIP_HORIZONTAL:
                result = rotateFlip(rotateFlip(img, RotationType.ROTATE_270), RotationType.FLIP_HORIZONTAL);
                return result;
            default:
                return img;
        }

        g.dispose();
        return result;
    }

    /**
     * 旋转类型枚举
     */
    private enum RotationType {
        ROTATE_90,
        ROTATE_180,
        ROTATE_270,
        FLIP_HORIZONTAL,
        FLIP_VERTICAL,
        ROTATE_90_FLIP_HORIZONTAL,
        ROTATE_270_FLIP_HORIZONTAL
    }

    /**
     * 获取EXIF方向信息（简化实现，实际需使用第三方库）
     * 注意：Java内置API不直接支持EXIF读取，此处返回0
     * 推荐使用metadata-extractor库实现真正的EXIF读取
     */
    private static int getExifOrientation(BufferedImage img) {
        // 实际实现参考：
        // https://github.com/drewnoakes/metadata-extractor
        return 0;
    }

    /**
     * 合并两张图片
     *
     * @param imgBack    背景图片
     * @param img        叠加图片
     * @param xDeviation X轴偏移量
     * @param yDeviation Y轴偏移量
     * @return 合并后的图片
     */
    public static BufferedImage combinImage(BufferedImage imgBack, BufferedImage img, int xDeviation, int yDeviation) {
        int bgWidth = imgBack.getWidth();
        int bgHeight = imgBack.getHeight();
        int imgWidth = img.getWidth();
        int imgHeight = img.getHeight();

        // 计算缩放比例
        float scale = (float) imgHeight / imgWidth;
        float bgScale = (float) bgWidth / bgHeight;

        // 调整叠加图片大小以适应背景
        if (bgScale > scale) {
            imgHeight = bgHeight;
            imgWidth = (int) (scale * imgHeight);
        } else {
            imgWidth = bgWidth;
            imgHeight = (int) (imgWidth / scale);
        }

        // 创建合并后的图片
        BufferedImage result = new BufferedImage(bgWidth, bgHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = result.createGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, bgWidth, bgHeight);
        g.drawImage(imgBack, 0, 0, bgWidth, bgHeight, null);

        // 计算叠加位置（居中 + 偏移）
        int x = (bgWidth - imgWidth) / 2 + xDeviation;
        int y = (bgHeight - imgHeight) / 2 + yDeviation;
        g.drawImage(img, x, y, imgWidth, imgHeight, null);

        g.dispose();
        imgBack.flush();
        img.flush();

        return result;
    }

    /**
     * 重载方法，使用默认偏移量
     */
    public static BufferedImage combinImage(BufferedImage imgBack, BufferedImage img) {
        return combinImage(imgBack, img, 0, 0);
    }
}