package simogl.model.modelloader;

import java.io.IOException;
import java.io.InputStream;

/**
 * Wrapper for an input stream
 * @author Malte
 *
 */
public class MD2InputStream extends InputStream{
	
	private InputStream input;
	private int byteCount;
	
	/**
	 * Konstruktor.
	 * @param input
	 */
	public MD2InputStream(InputStream input) {
		this.input = input;
	}
	
	/**
	 * @see java.io.InputStream#read()
	 */
	@Override
	public int read() throws IOException {
		return this.input.read();
	}
	
	/**
	 * Liest n Bytes aus.
	 * 
	 * @param numBytes  Anzahl der zu lesenden Bytes.
	 * @return Die gelesenen Bytes in Form eines Arrays.
	 * @throws IOException
	 */		
	public byte[] readBytes(int numBytes) throws IOException {
		byte[] bytes = new byte[numBytes];
		input.read(bytes);
		byteCount += numBytes;
		return bytes;			
	}
	
	
	/**
	 * Liest einen Int-Wert aus.
	 * 
	 * @return Gelesener Wert.
	 * @throws IOException
	 */
	public int readInt() throws IOException {
		
		byte[] bytes = readBytes(4);
				
		return ( (bytes[0] & 0xff) 
	           |((bytes[1] & 0xff) << 8)
	           |((bytes[2] & 0xff) << 16)
	           |((bytes[3] & 0xff) << 24) );	    
	}
	
	/**
	 * Liest einen Float-Wert aus.
	 * 
	 * @return Gelesener Wert.
	 * @throws IOException
	 */
	public float readFloat() throws IOException {
		return Float.intBitsToFloat(readInt());
	}
	
	/**
	 * Liest einen String aus.
	 * 
	 * @param length Länge des Strings.
	 * @return Gelesener String.
	 * @throws IOException
	 */
	public String readString(int length) throws IOException {
		return new String(readBytes(length));
	}
	
	/**
	 * Liest einen String aus. Es werden hierbei so
	 * lange Zeichen aus dem Stream gelesen, bis das
	 * Zeichen 0x00 erreicht wird.
	 * 
	 * @return Gelesener String.
	 * @throws IOException
	 */
	public String readString() throws IOException {
		String string = "";
		char symbol;
		while (true){
			symbol = (char) this.input.read();
			if (symbol != 0) {
				string += symbol;
			}
			else break;
		}
		return string;
	}
	
	
	/**
	 * Liest einen Short-Wert aus.
	 * 
	 * @return Gelesener Wert.
	 * @throws IOException
	 */
	public short readShort() throws IOException {
		byte[] bytes = readBytes(2);
		
		return (short) ( (bytes[0] & 0xff)
				       |((bytes[1]) << 8) );
	}
	
	
	/**
	 * Überspringt beliebig viele Bytes des Streams.
	 * 
	 * @param numBytes Anzahl der zu überspringenden Bytes.
	 * @throws IOException
	 */
	public void skip(int numBytes) throws IOException {
		input.skip(numBytes);
		byteCount += numBytes;
	}
	
	
	/**
	 * Gibt Aufschluss darüber, wie viele Bytes bereits gelesen
	 * wurden. Auch übersprungene Bytes gelten als gelesen.
	 * 
	 * @return Anzahl gelesener Bytes.
	 */
	public int getByteCount(){
		return this.byteCount;
	}
}
