package com.fuyuanshen.common.core.utils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 80*12像素点阵生成工具
 */
public class Bitmap80x12Generator {

    public static void main(String[] args) throws IOException {
        // 测试生成中文文本的点阵数据
        String text = "张三";
        byte[] bitmapData = generateFixedBitmapData(text, 120);
//        System.out.println(Arrays.toString(bitmapData));
        int[] ints = convertHexToDecimal(bitmapData);
        System.out.println(Arrays.toString(ints));
        // 生成预览图片
        byte[] bytes = convertDecimalToByteArray(ints);
        BufferedImage image = convertByteArrayToImage(bytes, 12, 80);
        ImageIO.write(image, "PNG", new File("D:\\bitmap_preview.png"));
        System.out.println("成功生成预览图片: D:\\bitmap_preview.png");

        // 打印十六进制数据
//        System.out.println("生成的点阵数据2:");
//        printHexData(bitmapData);
//        int[] ints = convertHexToDecimal(bitmapData);
        System.out.println("打印十进制无符号:" + Arrays.toString(ints));
//        printDecimalData(bitmapData);

        // 生成C文件
        generateCFile(bitmapData, "bitmap_data.c", "chinese_text");
    }

    /**
     * 将十进制整数数组转换为字节数组
     *
     * @param decimalArray 十进制整数数组（假设每个值都在0-255范围内）
     * @return 字节数组
     */
    public static byte[] convertDecimalToByteArray(int[] decimalArray) {
        if (decimalArray == null) {
            return new byte[0];
        }

        byte[] byteArray = new byte[decimalArray.length];
        for (int i = 0; i < decimalArray.length; i++) {
            // 确保值在0-255范围内，这是byte的无符号表示范围
            int value = decimalArray[i] & 0xFF;
            byteArray[i] = (byte) value;
        }

        return byteArray;
    }

    /**
     * 打印字节数组（以十进制形式显示）
     *
     * @param data 字节数组
     */
    public static void printByteArrayAsDecimal(byte[] data) {
        System.out.println("字节数组（十进制显示）:");
        for (int i = 0; i < data.length; i++) {
            // 将字节转换为无符号十进制数显示
            int value = data[i] & 0xFF;
            System.out.print(value);

            if (i < data.length - 1) {
                System.out.print(", ");
                if ((i + 1) % 12 == 0) {
                    System.out.println();
                }
            }
        }
        System.out.println();
    }


    /**
     * 将十六进制字节数组转换为十进制整数数组
     *
     * @param data 字节数组
     * @return 十进制整数数组
     */
    public static int[] convertHexToDecimal(byte[] data) {
        if (data == null) {
            return new int[0];
        }

        int[] decimalArray = new int[data.length];
        for (int i = 0; i < data.length; i++) {
            // 将字节转换为无符号整数（十进制）
            decimalArray[i] = data[i] & 0xFF;
        }

        return decimalArray;
    }

    /**
     * 打印十进制数据
     *
     * @param data 字节数组
     */
    public static void printDecimalData(byte[] data) {
        int[] decimalArray = convertHexToDecimal(data);

        System.out.println("生成的十进制数据:");
        for (int i = 0; i < decimalArray.length; i++) {
            System.out.print(decimalArray[i]);

            if (i < decimalArray.length - 1) {
                System.out.print(", ");
                if ((i + 1) % 12 == 0) {
                    System.out.println();
                }
            }
        }
        System.out.println();
    }

    public static void buildArr(int[] data, List<Integer> intData) {
        for (int datum : data) {
            intData.add(datum);
        }
    }

    /**
     * 生成固定长度的点阵数据
     *
     * @param text        要转换的文本
     * @param fixedLength 固定长度(字节)
     * @return 固定长度的点阵数据
     */
    public static byte[] generateFixedBitmapData(String text, int fixedLength) {
        if (text == null || text.isEmpty()) {
            return new byte[fixedLength];
        }

        // 创建80*12像素的图像
        Font font = new Font("宋体", Font.PLAIN, 12);
        BufferedImage image = createTextImage(text, font, 80, 12);

        // 提取点阵数据
        byte[] rawData = extractBitmapData(image);
//        System.out.println("生成的点阵数据1:");
//        System.out.println(Arrays.toString(rawData));

        // 调整到固定长度
        byte[] result = new byte[fixedLength];
        int copyLength = Math.min(rawData.length, fixedLength);
        System.arraycopy(rawData, 0, result, 0, copyLength);
        // 剩余部分自动初始化为0

        return result;
    }


    /**
     * 创建文本图像
     */
    private static BufferedImage createTextImage(String text, Font font, int width, int height) {
        // 创建图像
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();

        // 设置白色背景
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, width, height);

        // 设置黑色文本
        g.setColor(Color.BLACK);
        g.setFont(font);

        // 关闭抗锯齿
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
        g.setRenderingHint(RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);

        // 获取字体度量
        FontMetrics metrics = g.getFontMetrics();

        // 计算文本绘制位置(居中)
        int textWidth = metrics.stringWidth(text);
//        int x = Math.max(0, (width - textWidth) / 2); // 水平居中
        // 左对齐
        int x = 0;
        int y = (height - metrics.getHeight()) / 2 + metrics.getAscent(); // 垂直居中

        // 绘制文本
        g.drawString(text, x, y);

        g.dispose();
        return image;
    }

    /**
     * 提取点阵数据 - 从左到右，从上到下扫描
     */
    private static byte[] extractBitmapData(BufferedImage image) {
        int width = image.getWidth();
        int height = image.getHeight();

        List<Byte> byteList = new ArrayList<>();
        int currentByte = 0;
        int bitCount = 0;

        // 从上到下，从左到右扫描
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                // 获取像素颜色
                Color color = new Color(image.getRGB(x, y));

                // 判断是否为黑色(阈值处理)
                int gray = (color.getRed() + color.getGreen() + color.getBlue()) / 3;
                boolean isBlack = gray < 128;

                // 高位优先打包
                currentByte = (currentByte << 1) | (isBlack ? 1 : 0);
                bitCount++;

                if (bitCount == 8) {
                    byteList.add((byte) currentByte);
                    currentByte = 0;
                    bitCount = 0;
                }
            }
        }

        // 处理最后不满8位的部分
        if (bitCount > 0) {
            currentByte <<= (8 - bitCount);
            byteList.add((byte) currentByte);
        }

        return byteListToArray(byteList);
    }


    public static byte[] byteListToArray(List<Byte> byteList) {
        byte[] result = new byte[byteList.size()];
        for (int i = 0; i < byteList.size(); i++) {
            result[i] = byteList.get(i);
        }
        return result;
    }

    /**
     * 字节数组转图像
     */
    public static BufferedImage convertByteArrayToImage(byte[] data, int height, int width) {
        if (data == null || data.length == 0) {
            return new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
        }

        // 创建RGB图像
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        // 设置白色背景
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                image.setRGB(x, y, Color.WHITE.getRGB());
            }
        }

        // 从左到右，从上到下设置像素点
        int bitIndex = 0;
        for (int i = 0; i < data.length; i++) {
            int value = data[i] & 0xFF;
            for (int bit = 7; bit >= 0; bit--) { // 高位在前
                boolean isBlack = ((value >> bit) & 1) == 1;
                if (isBlack) {
                    int x = bitIndex % width;
                    int y = bitIndex / width;
                    if (x < width && y < height) { // 确保不越界
                        image.setRGB(x, y, Color.BLACK.getRGB());
                    }
                }
                bitIndex++;

                // 如果已经处理完所有像素，则退出
                if (bitIndex >= width * height) {
                    return image;
                }
            }
        }

        return image;
    }

    public static String convertToCArrayString(byte[] data, String arrayName) {
        StringBuilder sb = new StringBuilder();
        sb.append(String.format("// %s: %d 字节\n", arrayName, data.length));
        sb.append(String.format("const uint8_t %s[] = {\n    ", arrayName));

        for (int i = 0; i < data.length; i++) {
            sb.append(String.format("0x%02X", data[i] & 0xFF));

            if (i < data.length - 1) {
                sb.append(", ");
                // 每12个元素换行
                if ((i + 1) % 12 == 0) {
                    sb.append("\n    ");
                }
            }
        }

        sb.append("\n};");
        return sb.toString();
    }

    /**
     * 打印十六进制数据
     */
    private static void printHexData(byte[] data) {
        for (int i = 0; i < data.length; i++) {
            int value = data[i] & 0xFF;
            System.out.printf("0x%02X", value);

            if (i < data.length - 1) {
                System.out.print(", ");
                if ((i + 1) % 12 == 0) System.out.println();
            }
        }
        System.out.println();
    }

    /**
     * 生成C文件
     */
    public static void generateCFile(byte[] data, String filename, String arrayName) throws IOException {
        try (FileWriter writer = new FileWriter(filename)) {
            writer.write("/**\n");
            writer.write(" * 80*12点阵显示数据\n");
            writer.write(" * 数据大小: " + data.length + " 字节\n");
            writer.write(" * 分辨率: 80*12 像素\n");
            writer.write(" */\n\n");
            writer.write("#include <stdint.h>\n\n");

            writer.write(String.format("// %s: %d 字节, 80*12 像素\n", arrayName, data.length));
            writer.write(String.format("const uint8_t %s[] = {\n    ", arrayName));
            writeByteArray(writer, data);
            writer.write("\n};\n");
        }
    }


    private static void writeByteArray(FileWriter writer, byte[] data) throws IOException {
        for (int i = 0; i < data.length; i++) {
            int value = data[i] & 0xFF;
            writer.write(String.format("0x%02X", value));

            if (i < data.length - 1) {
                writer.write(", ");
                if ((i + 1) % 12 == 0) writer.write("\n    ");
            }
        }
    }


}
