package org.eclipse.swt.internal.image;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved
 */

import java.io.*;
import org.eclipse.swt.*;

public class PngDecodingDataStream {
	PngIdatChunk currentChunk;
	PngChunkReader chunkReader;
	byte currentByte;
	int nextByteIndex;
	int nextBitIndex;
	
	PngLzBlockReader lzBlockReader;
	int adlerValue;
	
	static final int PRIME = 65521;
	static final int MAX_BIT = 7;		
	
PngDecodingDataStream(PngIdatChunk idatChunk, PngChunkReader chunkReader) {
	super();
	this.currentChunk = idatChunk;
	this.chunkReader = chunkReader;
	nextByteIndex = 0;
	nextBitIndex = MAX_BIT + 1;
	adlerValue = 1;
	lzBlockReader = new PngLzBlockReader(this);
	readCompressedDataHeader();
	lzBlockReader.readNextBlockHeader();
}

/**
 * This method should be called when the image decoder thinks
 * that all of the compressed image data has been read. This
 * method will ensure that the next data value is an end of 
 * block marker. If there are more blocks after this one,
 * the method will read them and ensure that they are empty.
 */
void assertImageDataAtEnd() {
	lzBlockReader.assertCompressedDataAtEnd();
}

int getNextIdatBits(int length) {
	int value = 0;
	for (int i = 0; i < length; i++) {
		value |= (getNextIdatBit() << i);
	}
	return value;
}

byte getNextIdatBit() {
	if (nextBitIndex > MAX_BIT) {
		currentByte = getNextIdatByte();
		nextBitIndex = 0;
	}	
	int mask = 1 << nextBitIndex;
	nextBitIndex++;
	return ((currentByte & mask) > 0) ? (byte) 1 : (byte) 0;	
}

private PngIdatChunk getNextChunk() {
	PngChunk chunk = chunkReader.readNextChunk();
	if (chunk == null) error();
	if (chunk.getChunkType() != PngChunk.CHUNK_IDAT) error(); 
	return (PngIdatChunk) chunk;
}

byte getNextIdatByte() {
	if (nextByteIndex > currentChunk.getLength() - 1) {
		currentChunk = getNextChunk();
		nextByteIndex = 0;
	}
	byte nextByte = currentChunk.getDataByteAtOffset(nextByteIndex);
	nextByteIndex++;
	nextBitIndex = MAX_BIT + 1;
	return nextByte;
}

private void updateAdler(byte value) {
	int low = adlerValue & 0xFFFF;
	int high = (adlerValue >> 16) & 0xFFFF;
	int valueInt = value & 0xFF;
	low = (low + valueInt) % PRIME;
	high = (low + high) % PRIME;
	adlerValue = (high << 16) | low;
}

byte getNextDecodedByte() {
	byte nextDecodedByte = lzBlockReader.getNextByte();
	updateAdler(nextDecodedByte);
	return nextDecodedByte;
}

void error() {
	SWT.error(SWT.ERROR_INVALID_IMAGE);
}

private void readCompressedDataHeader() {
	byte headerByte1 = getNextIdatByte();
	byte headerByte2 = getNextIdatByte();
	
	int number = ((headerByte1 & 0xFF) << 8) | (headerByte2 & 0xFF);
	if (number % 31 != 0) error();
	
	int compressionMethod = headerByte1 & 0x0F;
	if (compressionMethod != 8) error();
	
	int windowSizeHint = (headerByte1 & 0xF0) >> 4;
	if (windowSizeHint > 7) error();
	int windowSize = (1 << (windowSizeHint + 8));
	lzBlockReader.setWindowSize(windowSize);
	
	int dictionary = (headerByte2 & (1 << 5));
	if (dictionary != 0) error();
	
	int compressionLevel = (headerByte2 & 0xC0) >> 6;
}

void checkAdler() {
	int storedAdler = ((getNextIdatByte() & 0xFF) << 24)
		| ((getNextIdatByte() & 0xFF) << 16)
		| ((getNextIdatByte() & 0xFF) << 8)
		| (getNextIdatByte() & 0xFF);
	if (storedAdler != adlerValue) error();
}

}
