package org.kne.codec.kif;

import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.processing.SupportedSourceVersion;

/**
 * 字节值频率统计与映射表生成工具
 * 用于调色板模式中的字节级概率空间映射
 */
public class ByteFrequencyMapper {
    
    /**
     * 统计字节数组中每个值（0~255）出现的次数
     * 
     * @param data 输入的字节数组
     * @return 长度为 256 的 int 数组，index 表示字节值，value 表示出现次数
     */
    public static int[] buildFrequency(byte[] data) {
        int[] freq = new int[256];
        for (byte b : data) {
            freq[b & 0xFF]++;
        }
        return freq;
    }
    
    /**
     * 根据频率数组生成映射表（按频率降序排列）
     * 映射表：index -> byte value
     * 即：映射表[0] = 出现次数最多的字节值
     * 
     * @param freq 长度为 256 的频率数组
     * @return 长度为 256 的 byte 数组，按频率降序排列
     */
    public static byte[] buildInverseMap(int[] freq) {
        // 创建索引数组 0~255
        Integer[] indices = new Integer[256];
        for (int i = 0; i < 256; i++) {
            indices[i] = i;
        }
        
        // 按频率降序排序
        Arrays.sort(indices, new Comparator<Integer>() {
            @Override
            public int compare(Integer a, Integer b) {
                // 频率高的排前面
                int cmp = Integer.compare(freq[b], freq[a]);
                if (cmp != 0) return cmp;
                // 频率相同，按值升序
                return Integer.compare(a, b);
            }
        });
        
        // 生成映射表
        byte[] forwardMap = new byte[256];
        for (int i = 0; i < 256; i++) {
            forwardMap[i] = (byte) indices[i].intValue();
        }
        return forwardMap;
    }
    
    /**
     * 生成逆映射表
     * 逆映射表：byte value -> index
     * 即：inverseMap[原始字节值] = 在映射表中的位置
     * 
     * @param map 正向映射表（index -> byte value）
     * @return 长度为 256 的 byte 数组，逆映射表
     */
    public static byte[] inverse(byte[] map) {
        byte[] inverseMap = new byte[256];
        for (int i = 0; i < map.length; i++) {
            int value = map[i] & 0xFF;
            inverseMap[value] = (byte) i;
        }
        return inverseMap;
    }
    
    /**
     * 使用映射表对字节数组进行映射（编码）
     * 
     * @param data 原始字节数组
     * @param forwardMap 映射表
     * @return 映射后的字节数组
     */
    public static byte[] applyMap(byte[] data, byte[] forwardMap) {
        byte[] result = new byte[data.length];
        for (int i = 0; i < data.length; i++) {
            int value = data[i] & 0xFF;
            // 查找该值在映射表中的位置
            // 注意：如果 forwardMap 是压缩的（只包含部分值），需要处理未映射的情况
            // 这里假设 forwardMap 是全映射
            result[i] = forwardMap[value];
        }
        return result;
    }
    
  
    
    /**
     * 截断映射表：只保留前 K 个高频值，其余映射到最近的高频值
     * 
     * @param freq 频率数组
     * @param k 保留的高频值数量（1~256）
     * @return 截断后的映射表（长度仍然为 256，但只包含 K 种唯一值）
     */
    public static byte[] buildTruncatedForwardMap(int[] freq, int k) {
        if (k <= 0 || k > 256) {
            throw new IllegalArgumentException("k 必须在 1~256 之间");
        }
        
        // 获取完整映射表
        byte[] fullMap = buildInverseMap(freq);
        
        // 取前 k 个高频值
        byte[] truncated = new byte[256];
        // 初始化为 0（默认映射到第一个高频值）
        Arrays.fill(truncated, fullMap[0]);
        
        // 将前 k 个高频值放入映射表
        for (int i = 0; i < k; i++) {
            truncated[i] = fullMap[i];
        }
        
        // 对于低频值，需要建立逆映射：原始字节值 -> 最近的高频值索引
        // 这里简化为：低频值全部映射到索引 0（最高频值）
        // 更精细的做法可以是：找到最近的映射表值
        
        return truncated;
    }
    
    /**
     * 获取映射表的统计信息
     */
    public static String getMapStats(byte[] forwardMap, int[] freq) {
        int total = 0;
        for (int f : freq) {
            total += f;
        }
        
        StringBuilder sb = new StringBuilder();
        sb.append("映射表统计:\n");
        sb.append("  唯一值数: ").append(getUniqueCount(forwardMap)).append("\n");
        
        long covered = 0;
        int threshold = 99;
        for (int i = 0; i < forwardMap.length; i++) {
            int value = forwardMap[i] & 0xFF;
            covered += freq[value];
            double pct = covered * 100.0 / total;
            if (pct >= threshold && i > 0) {
                sb.append(String.format("  前 %d 个值覆盖 %.2f%% 的像素\n", i + 1, pct));
                break;
            }
        }
        
        double pct = covered * 100.0 / total;
        sb.append(String.format("  全部值覆盖 %.2f%% 的像素\n", pct));
        return sb.toString();
    }
    
    private static int getUniqueCount(byte[] map) {
        boolean[] seen = new boolean[256];
        int count = 0;
        for (byte b : map) {
            int value = b & 0xFF;
            if (!seen[value]) {
                seen[value] = true;
                count++;
            }
        }
        return count;
    }
    public static void main(String[] args) {
    	 byte[] serialData = new byte[] {1,1,1,1,1,0,0,0,2,3,3,3,3,3,3,3,4};
		int[]freq=ByteFrequencyMapper.buildFrequency(serialData);
         byte[]inverse=ByteFrequencyMapper.buildInverseMap(freq);
         byte[]foward=ByteFrequencyMapper.inverse(inverse);
         byte[] serialDatafor= ByteFrequencyMapper.applyMap(serialData, foward);
         System.out.println("输入：");
         ByteStatisticsCollector bsc=new ByteStatisticsCollector();
         bsc.analyze(serialData);
         System.out.println(bsc);

         System.out.println("编码：");
         ByteStatisticsCollector bsc2=new ByteStatisticsCollector();
         bsc2.analyze(serialDatafor);
         System.out.println(bsc2);
         
         byte[] serialDatainv= ByteFrequencyMapper.applyMap(serialDatafor, inverse);
         System.out.println("解码：");
         ByteStatisticsCollector bsc32=new ByteStatisticsCollector();
         bsc32.analyze(serialDatainv);
         System.out.println(bsc32);
	}
}