/**
 * 
 */
package jp.sourceforge.nicoro.swf;

import static jp.sourceforge.nicoro.swf.Log.DEBUG_LOGV;
import static jp.sourceforge.nicoro.swf.Log.DEBUG_LOGD;
import static jp.sourceforge.nicoro.swf.Log.LOG_TAG;

import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import jp.sourceforge.nicoro.FailAnalyzeSwfException;
import jp.sourceforge.nicoro.Util;

public class RECORDHEADER {
	// Tag ひとまず使うものだけ
	public static final int SWFTAG_END = 0;
	public static final int SWFTAG_SHOWFRAME = 1;
	public static final int SWFTAG_DEFINESHAPE = 2;
	public static final int SWFTAG_SETBACKGROUNDCOLOR = 9;
	public static final int SWFTAG_SOUNDSTREAMHEAD = 18;
	public static final int SWFTAG_SOUNDSTREAMBLOCK = 19;
	public static final int SWFTAG_DEFINEBITSJPEG2 = 21;
	public static final int SWFTAG_DEFINESHAPE2 = 22;
	public static final int SWFTAG_PLACEOBJECT2 = 26;
	public static final int SWFTAG_REMOVEOBJECT2 = 28;
	public static final int SWFTAG_DEFINESHAPE3 = 32;
	public static final int SWFTAG_DEFINEBITSLOSSLESS2 = 36;
	public static final int SWFTAG_FILEATTRIBUTES = 69;
	public static final int SWFTAG_DEFINESHAPE4 = 83;
	
	public short tagType;		// 10bit
	public byte tagLength;		// 6bit
	public int tagLengthLong;	// SI32

    public void read(InputStream inSwf)
    throws IOException, FailAnalyzeSwfException {
    	RECORDHEADER tagBlock = this;
    	
    	byte[] taglength = new byte[2];
    	int readSize = Util.readComplete(inSwf, taglength);
    	if (readSize != taglength.length) {
    		throw new FailAnalyzeSwfException("tag block tag & length read failed: " + readSize);
    	}
    	if (DEBUG_LOGV) {
    		Log.v(LOG_TAG, Log.buf().append("SWF tag block taglength=")
    				.append(String.format("%02X,%02X", taglength[0], taglength[1])).toString());
    	}
    	tagBlock.tagType = (short) (((taglength[1] << 2) | ((taglength[0] & 0xff) >>> 6)) & 0x3ff);
    	tagBlock.tagLength = (byte) (taglength[0] & 0x3f);
    	if (DEBUG_LOGV) {
    		Log.v(LOG_TAG, Log.buf().append("SWF tag block tag=").append(tagBlock.tagType)
    				.append(" length=").append(tagBlock.tagLength).toString());
    	}
    	
    	if (isTagBlockLong(tagBlock.tagType, tagBlock.tagLength)) {
        	ByteBuffer lengthLongBuffer = ByteBuffer.allocate(4);
        	lengthLongBuffer.order(ByteOrder.LITTLE_ENDIAN);
        	readSize = Util.readComplete(inSwf, lengthLongBuffer.array());
        	if (readSize != lengthLongBuffer.array().length) {
        		throw new FailAnalyzeSwfException("tag block long length read failed: " + readSize);
        	}
        	tagBlock.tagLengthLong = lengthLongBuffer.getInt();
        	if (DEBUG_LOGV) {
        		Log.v(LOG_TAG, Log.buf().append("SWF tag block long length=")
        				.append(tagBlock.tagLengthLong).toString());
        	}
    	} else {
    		tagBlock.tagLengthLong = -1;
    	}
    }
    
    public void read(RandomAccessFile inSwf)
    throws IOException, FailAnalyzeSwfException {
    	RECORDHEADER tagBlock = this;
    	
    	byte[] taglength = new byte[2];
    	int readSize = Util.readComplete(inSwf, taglength);
    	if (readSize != taglength.length) {
    		throw new FailAnalyzeSwfException("tag block tag & length read failed: " + readSize);
    	}
    	if (DEBUG_LOGV) {
    		Log.v(LOG_TAG, Log.buf().append("SWF tag block taglength=")
    				.append(String.format("%02X,%02X", taglength[0], taglength[1])).toString());
    	}
    	tagBlock.tagType = (short) (((taglength[1] << 2) | ((taglength[0] & 0xff) >>> 6)) & 0x3ff);
    	tagBlock.tagLength = (byte) (taglength[0] & 0x3f);
    	if (DEBUG_LOGV) {
    		Log.v(LOG_TAG, Log.buf().append("SWF tag block tag=").append(tagBlock.tagType)
    				.append(" length=").append(tagBlock.tagLength).toString());
    	}
    	
    	if (isTagBlockLong(tagBlock.tagType, tagBlock.tagLength)) {
        	ByteBuffer lengthLongBuffer = ByteBuffer.allocate(4);
        	lengthLongBuffer.order(ByteOrder.LITTLE_ENDIAN);
        	readSize = Util.readComplete(inSwf, lengthLongBuffer.array());
        	if (readSize != lengthLongBuffer.array().length) {
        		throw new FailAnalyzeSwfException("tag block long length read failed: " + readSize);
        	}
        	tagBlock.tagLengthLong = lengthLongBuffer.getInt();
        	if (DEBUG_LOGV) {
        		Log.v(LOG_TAG, Log.buf().append("SWF tag block long length=")
        				.append(tagBlock.tagLengthLong).toString());
        	}
    	} else {
    		tagBlock.tagLengthLong = -1;
    	}
    }
    
    private static boolean isTagBlockLong(short tag, byte length) {
    	// TODO 特別なtagの判定
    	
    	return length == 0x3f;
    }
    
}