package com.ktg.common.utils.face;

import cn.hutool.core.lang.Assert;
import com.ktg.common.config.RuoYiConfig;
import com.ktg.common.utils.FileDriveLetterUtils;
import com.ktg.common.utils.StringUtils;
import com.ktg.common.vo.FaceCutVO;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 面部裁剪工具
 *
 * @author cgj
 */
public class FaceCutUtil
{



    // 初始化人脸探测器
    static CascadeClassifier faceDetector;
    /**
     * 图片人脸检测
     */
    public static FaceCutVO imageFaceDetection(MultipartFile file, Long userId, String url) throws IOException {
        String prodApi = RuoYiConfig.getProd();
        // ------------------------加载OpenCV本地库--------------------------------------------
        // System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        String loadPath = "/guoruan/app/opencv/build/java/x64/opencv_java470.dll";
        if (StringUtils.isBlank(prodApi)) {
            loadPath = "C:/work/app/install/opencv/build/java/x64/opencv_java470.dll";
        }
        System.load(loadPath);
        // 从配置文件lbpcascade_frontalface.xml中创建一个人脸识别器，文件位于opencv安装目录中
        String faceDetectorPath = "/guoruan/app/opencv/sources/data/haarcascades/haarcascade_frontalface_alt.xml";
        if (StringUtils.isBlank(prodApi)) {
            faceDetectorPath = "C:/work/app/install/opencv/sources/data/haarcascades/haarcascade_frontalface_alt.xml";
        }
        faceDetector = new CascadeClassifier(faceDetectorPath);

        // -------------------- 定义文件的基础属性----------------------------
        // 人脸存储基础路径
        String profile = RuoYiConfig.getProfile();
        String basePath = FileDriveLetterUtils.getDriveLetter() + profile + "/face/" + userId +"/";
        /*if (StringUtils.isBlank(prodApi)) {
            basePath = "C:" + basePath;
        }*/
        // 原文件裁剪后的路径
        String content;
        // 原文件转存后的路径
        String imagePath;
        // 原文件转存后的前端请求路径
        String imageUrl = null;

        // 时间戳
        long currentTimestamp = System.currentTimeMillis();
        // 设置文件路径
        String filePath = basePath ;
        // 确保目录存在，不存在则创建一个
        Path uploadPath = Paths.get(filePath);
        if (!Files.exists(uploadPath)) {
            Files.createDirectories(uploadPath);
        }
        // 获取文件名并构建目标路径
        String fileName = userId + "_" + currentTimestamp + "_" + file.getOriginalFilename();
        Path targetLocation = uploadPath.resolve(fileName);
        imagePath = filePath + fileName;
        // 获取前端的请求路径地址
        /*if (imagePath.contains("C:" + profile)) {
            imageUrl = imagePath.replace("C:" + profile, url + "/profile");
        } else if (imagePath.contains(profile)) {
            imageUrl = imagePath.replace(profile, url + "/prod-api" + "/profile");
        }*/
        if (StringUtils.isBlank(prodApi)) {
            imageUrl = imagePath.replace(FileDriveLetterUtils.getDriveLetter() + profile, url + "/profile");
        } else {
            imageUrl = imagePath.replace(FileDriveLetterUtils.getDriveLetter() + profile, url + "/prod-api" + "/profile");
        }
        // 将文件写入目标路径
        file.transferTo(targetLocation.toFile());

        // 读取测试图片
        Mat image = Imgcodecs.imread(imagePath);
        if (image.empty()) {
            throw new RuntimeException("图片内存为空");
        }

        // 检测脸部
        MatOfRect face = new MatOfRect();
        // 检测图像中的人脸
        faceDetector.detectMultiScale(image, face);
        // 匹配Rect矩阵
        Rect[] rects = face.toArray();
        System.out.println("识别人脸个数： " + rects.length);
        Assert.isFalse(rects.length > 1, "识别到多张人脸，请重新调整位置！");

        // 识别图片中的所有人脸并分别保存
        // int i = 1;
        // 上面做了限制，现在其实只会有一张人脸
        FaceCutVO faceCutVO = new FaceCutVO();
        for (Rect rect : face.toArray()) {
            Imgproc.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0), 3);
            // 进行图片裁剪
            String cutImgName = userId + "_" + currentTimestamp + "_cut.jpg";
            content = filePath + cutImgName;
            imageCut(imagePath, content, rect.x, rect.y, rect.width, rect.height);
            // i++;
            faceCutVO.setUserId(userId);
            faceCutVO.setType("2");
            faceCutVO.setContent(content);
            faceCutVO.setImageUrl(imageUrl);
            faceCutVO.setImagePath(imagePath);
        }
        // ---------------------以下为前端的裁剪动画展示--------------------
        // 图片中人脸画框保存到本地
        // Imgcodecs.imwrite("C:/work/file/test1.png", image);
        // 展示图片
        // HighGui.imshow("人脸识别", image);
        // HighGui.waitKey(0);

        return faceCutVO;
    }

    /**
     * 裁剪人脸
     *
     * @param readPath 读取文件路径
     * @param outPath  写出文件路径
     * @param x        坐标X
     * @param y        坐标Y
     * @param width    截图宽度
     * @param height   截图长度
     */
    public static void imageCut(String readPath, String outPath, int x, int y, int width, int height) {
        // 原始图像
        Mat image = Imgcodecs.imread(readPath);
        // 截取的区域
        Rect rect = new Rect(x, y, width, height);
        Mat sub = new Mat(image,rect);
        // Mat sub = image.submat(rect);
        Mat mat = new Mat();
        Size size = new Size(width, height);
        // 人脸进行截图并保存
        Imgproc.resize(sub, mat, size);
        Imgcodecs.imwrite(outPath, mat);
    }
}
