package org.kne.codec.kif;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Arrays;

import org.kne.membandboost.MembandBoost;

public class KIFCompressedImageBlock implements Comparable<KIFCompressedImageBlock>{
    private byte[] data;
    private int sizeBeforeCompress;
    private int width;
    private int height;
    private int posx;
    private int posy;
    private KIFCompressMode predictMode;  // 预测模式 (0=H+V, 1=TL+TR, 等)

    public KIFCompressedImageBlock(byte[] data, int sizeBeforeCompress, int width, int height, 
                                    int posx, int posy, KIFCompressMode predictMode) {
        super();
        this.data = data;
        this.sizeBeforeCompress = sizeBeforeCompress;
        this.width = width;
        this.height = height;
        this.posx = posx;
        this.posy = posy;
        this.predictMode = predictMode;
    }

    // ==================== I/O 方法 ====================

    /**
     * 从 DataInput 读取一个压缩块
     * 格式：
     *   [predictMode 1B] [预留 3B]
     *   [width 4B] [height 4B] [posx 4B] [posy 4B]
     *   [sizeBeforeCompress 4B] [dataLength 4B] [data N B]
     * 
     * @param in DataInput 源
     * @return 读取到的 KIFCompressedImageBlock
     * @throws IOException 如果读取失败
     */
    public static KIFCompressedImageBlock readFromStream(DataInput in) throws IOException {
        // 1. 读取预测模式
        byte predictMode = in.readByte();

        // 2. 跳过预留字节 (3 bytes)
        in.skipBytes(1);

        // 3. 读取元数据
        int width = in.readInt();
        int height = in.readInt();
        int posx = in.readInt();
        int posy = in.readInt();
        int sizeBeforeCompress = in.readInt();
        int dataLength = in.readInt();

        // 4. 读取数据
        byte[] data = MembandBoost.allocateUninitializedByteArray(dataLength);
        in.readFully(data);

        return new KIFCompressedImageBlock(data, sizeBeforeCompress, width, height, posx, posy,new KIFCompressMode( predictMode));
    }

    /**
     * 将当前块写入 DataOutput
     * 
     * @param out DataOutput 目标
     * @throws IOException 如果写入失败
     */
    public void writeToStream(DataOutput out) throws IOException {
        // 1. 写入预测模式
        out.writeByte(predictMode.getMode());

        // 2. 预留字节 (1 bytes)
        out.writeByte(0);

        // 3. 写入元数据
        out.writeInt(width);
        out.writeInt(height);
        out.writeInt(posx);
        out.writeInt(posy);
        out.writeInt(sizeBeforeCompress);
        out.writeInt(data.length);

        // 4. 写入数据
        out.write(data);
    }

    /**
     * 计算写入流时需要的字节数
     */
    public int getSerializedSize() {
        return 1 + 3 + 6 * 4 + data.length;
    }

    // ==================== 静态工厂方法 ====================

    public static KIFCompressedImageBlock fromIntImageBlock(IntImageBlock block, byte[] compressedData, 
                                                             int sizeBeforeCompress, KIFCompressMode predictMode) {
        return new KIFCompressedImageBlock(
            compressedData,
            sizeBeforeCompress,
            block.getWidth(),
            block.getHeight(),
            block.getPosx(),
            block.getPosy(),
            predictMode
        );
    }

    // ==================== Getters/Setters ====================

    public byte[] getData() {
        return data;
    }

    public int getSizeBeforeCompress() {
        return sizeBeforeCompress;
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    public int getPosx() {
        return posx;
    }

    public int getPosy() {
        return posy;
    }

    public KIFCompressMode getPredictMode() {
        return predictMode;
    }

 

    // ==================== toString / hashCode / equals ====================

    @Override
    public String toString() {
        return "KIFCompressedImageBlock[" + width + "x" + height + ",(" + posx + "," + posy + "),mode=" + predictMode + "," + data.length + "B,src=" + sizeBeforeCompress + "B]";
    }

    @Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + Arrays.hashCode(data);
		result = prime * result + height;
		result = prime * result + posx;
		result = prime * result + posy;
		result = prime * result + ((predictMode == null) ? 0 : predictMode.hashCode());
		result = prime * result + sizeBeforeCompress;
		result = prime * result + width;
		return result;
	}

    @Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		KIFCompressedImageBlock other = (KIFCompressedImageBlock) obj;
		if (!Arrays.equals(data, other.data))
			return false;
		if (height != other.height)
			return false;
		if (posx != other.posx)
			return false;
		if (posy != other.posy)
			return false;
		if (predictMode == null) {
			if (other.predictMode != null)
				return false;
		} else if (!predictMode.equals(other.predictMode))
			return false;
		if (sizeBeforeCompress != other.sizeBeforeCompress)
			return false;
		if (width != other.width)
			return false;
		return true;
	}

	@Override
	public int compareTo(KIFCompressedImageBlock o) {
		int v=Integer.compare(data.length, o.data.length);
		if(v==0) {
		return Integer.compare(predictMode.getEnableCount(), o.predictMode.getEnableCount())	;
		}else {
		return v;
		}
	}
	
	
	
}