package org.kne.codec.kif;

import java.util.ArrayList;
import java.util.List;

public class KIFCompressMode {
    private int mode;

    public KIFCompressMode(int mode) {
        super();
        this.mode = mode;
    }

    public int getMode() {
        return mode;
    }

    // ==================== 6个bit的getter方法 ====================

    /**
     * 是否启用水平预测 (H)
     */
    public boolean isH() {
        return (mode & 0b0001) != 0;
    }

    /**
     * 是否启用垂直预测 (V)
     */
    public boolean isV() {
        return (mode & 0b0010) != 0;
    }

    /**
     * 是否启用左上角预测 (TL)
     */
    public boolean isTL() {
        return (mode & 0b0100) != 0;
    }

    /**
     * 是否启用右上角预测 (TR)
     */
    public boolean isTR() {
        return (mode & 0b1000) != 0;
    }

    /**
     * 是否启用颜色差分 (CD)
     */
    public boolean isCD() {
        return (mode & 0b10000) != 0;
    }

    /**
     * 是否启用位平面 (BP)
     */
    public boolean isBP() {
        return (mode & 0b100000) != 0;
    }
    

    /**
     * 是否启用平面序列化 (PL)
     * 启用后，像素按 RRRGGGBBB 顺序存储，而非 RGBRGBRGB
     * 对屏幕内容可能有更好的压缩率
     */
    public boolean isPL() {
        return (mode & 0b1000000) != 0;
    }

    // ==================== 批量判断 ====================

    /**
     * 检查是否启用了任何预测器 (H/V/TL/TR)
     */
    public boolean hasAnyPredictor() {
        return (mode & 0b1111) != 0;
    }

    /**
     * 获取预测器部分（低4位）
     */
    public int getPredictorBits() {
        return mode & 0b1111;
    }

    /**
     * 获取当前启用的预测器数量
     */
    public int getPredictorCount() {
        int count = 0;
        int n = mode & 0b1111;
        while (n != 0) {
            count++;
            n &= (n - 1);
        }
        return count;
    }
    
    public int getEnableCount() {
    	return bitcount(mode&0xff);
    }
    
    private static int bitcount ( int n)
	{
	    int count=0 ;
	    while (n!=0) {
	        count++ ;
	        n &= (n - 1) ;
	    }
	    return count ;
	}
    // ==================== 原有的hashCode/equals/toString ====================

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + mode;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        KIFCompressMode other = (KIFCompressMode) obj;
        if (mode != other.mode)
            return false;
        return true;
    }

    /**
     * 将模式编号转换为可读的预测器组合字符串
     */
    private static String modeToString(int mode) {
        StringBuilder sb = new StringBuilder();
        if ((mode & 0b0001) != 0) sb.append("H ");
        if ((mode & 0b0010) != 0) sb.append("V ");
        if ((mode & 0b0100) != 0) sb.append("TL ");
        if ((mode & 0b1000) != 0) sb.append("TR ");
        if ((mode & 0b10000) != 0) sb.append("CD ");
        if ((mode & 0b100000) != 0) sb.append("BP ");
        if ((mode & 0b1000000) != 0) sb.append("PL ");
        if (sb.length() == 0) sb.append("0 ");
        return sb.toString().trim();
    }

    @Override
    public String toString() {
        return modeToString(mode) + "(" + mode + ")";
    }

	public static List<KIFCompressMode> getAllModes() {
		List<KIFCompressMode> result=new ArrayList<>(64);
		for(int i=0;i<128;i++) {
			KIFCompressMode mode=new KIFCompressMode(i);
			if(mode.isTL()||mode.isTR()) {
				continue;
			}
			result.add(mode);
		}
		return result;
	}public static List<KIFCompressMode> getNaturalImageModes() {
	    List<KIFCompressMode> result = new ArrayList<>(16);
	    // 自然图像中最常用的模式（按优先级排序）
	    result.add(new KIFCompressMode(115)); // H V CD BP PL(115)
	    result.add(new KIFCompressMode(114)); // V CD BP PL(114)
	    result.add(new KIFCompressMode(113)); // H CD BP PL(113)
	    return result;
	}

	public static List<KIFCompressMode> getScreenImageModes() {
	    List<KIFCompressMode> result = new ArrayList<>(16);
	    // 屏幕图像中最常用的模式（按优先级排序）
	    result.add(new KIFCompressMode(0));//0(0)
	    result.add(new KIFCompressMode(114));// V CD BP PL(114)
	    result.add(new KIFCompressMode(16)); // CD(16)
	    result.add(new KIFCompressMode(80)); // CD PL(80)
	    result.add(new KIFCompressMode(17)); // H CD(17)
	    result.add(new KIFCompressMode(34)); // V BP(34)
	    result.add(new KIFCompressMode(115)); // H V CD BP PL(115) 
	    return result;
	}
}