package com.swiftcleaner.chovey.model.bean;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.media.ThumbnailUtils;

import java.io.File;

/**
 * 作者：马海钊
 * 时间：2024/12/18 16:47
 * 功能：
 */
public class ImageHelpers {
    // 加载 Bitmap 从文件路径
    private static Bitmap loadBitmapFromFile(String path) {
        Bitmap bitmap = BitmapFactory.decodeFile(path);
        if (bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
            return null;
        }
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);
        if (options.outHeight == -1 || options.outWidth == -1) {
            return null;
        }
        int inSampleSize = (int) (0.5f + options.outHeight / (float) bitmap.getHeight()) >= (int) (0.5f + options.outWidth / (float) bitmap.getWidth())
                ? (int) (0.5f + options.outHeight / (float) bitmap.getHeight()) : (int) (0.5f + options.outWidth / (float) bitmap.getWidth());
        inSampleSize++;
        options.inSampleSize = inSampleSize >= 1 ? inSampleSize : 1;
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(path, options);
    }

    // 创建图片的相似性对象
    public static SimilarBean createImage(String path) {
        try {
            int width = 8;
            int height = 8;
            Bitmap source = loadBitmapFromFile(path);
            Bitmap thumb = ThumbnailUtils.extractThumbnail(source, width, height);
            int[] pixels = new int[width * height];
            for (int i = 0; i < width; i++) {
                for (int j = 0; j < height; j++) {
                    pixels[i * height + j] = rgbToGray(thumb.getPixel(i, j));
                }
            }
            int avgPixel = average(pixels);
            int[] comps = new int[width * height];
            for (int i = 0; i < comps.length; i++) {
                if (pixels[i] >= avgPixel) {
                    comps[i] = 1;
                } else {
                    comps[i] = 0;
                }
            }
            StringBuilder hashCode = new StringBuilder();
            for (int i = 0; i < comps.length; i += 4) {
                int result = comps[i] * (int) Math.pow(2, 3) + comps[i + 1] * (int) Math.pow(2, 2) + comps[i + 2] * (int) Math.pow(2, 1) + comps[i + 3];
                hashCode.append(binaryToHex(result));
            }
            recycleBitmap(thumb);
            recycleBitmap(source);
            return new SimilarBean(path, hashCode.toString(), avgPixel, new File(path).length(), false);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    // 将 RGB 值转换为灰度值
    private static int rgbToGray(int pixels) {
        int red = Color.red(pixels);
        int green = Color.green(pixels);
        int blue = Color.blue(pixels);
        return (int) (0.3 * red + 0.59 * green + 0.11 * blue);
    }

    // 计算像素数组的平均值
    private static int average(int[] pixels) {
        int sum = 0;
        for (int pixel : pixels) {
            sum += pixel;
        }
        return sum / pixels.length;
    }

    // 回收 Bitmap
    private static void recycleBitmap(Bitmap thumb) {
        if (thumb != null && !thumb.isRecycled()) {
            thumb.recycle();
        }
    }

    // 判断两张图片的相似性条件
    public static boolean similarCondition(SimilarBean first, SimilarBean second) {
        return hammingDistance(first.getHashCode(), second.getHashCode()) <= 6 && (first.getAvgPixel() / (float) second.getAvgPixel()) >= 0.8 && (first.getAvgPixel() / (float) second.getAvgPixel()) <= 1.0;
    }

    // 计算汉明距离
    private static int hammingDistance(String sourceHashCode, String hashCode) {
        int difference = 0;
        for (int i = 0; i < sourceHashCode.length(); i++) {
            if (sourceHashCode.charAt(i) != hashCode.charAt(i)) {
                difference++;
            }
        }
        return difference;
    }

    // 将二进制转换为十六进制
    private static char binaryToHex(int binary) {
        switch (binary) {
            case 0:
                return '0';
            case 1:
                return '1';
            case 2:
                return '2';
            case 3:
                return '3';
            case 4:
                return '4';
            case 5:
                return '5';
            case 6:
                return '6';
            case 7:
                return '7';
            case 8:
                return '8';
            case 9:
                return '9';
            case 10:
                return 'a';
            case 11:
                return 'b';
            case 12:
                return 'c';
            case 13:
                return 'd';
            case 14:
                return 'e';
            case 15:
                return 'f';
            default:
                return ' ';
        }
    }
}
