// 一部未実装。本来は吉里吉里側で実装
package jp.kirikiri.tjs2;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;


public class TextReadStream {

	private InputStream mStream;
	private InputStreamReader mReader;
	private int mCryptMode;
	private boolean mDirectLoad;

	public TextReadStream(final String name, final String modestr ) throws TJSException {
		try {
			mCryptMode = -1;
			mDirectLoad = false;
			mStream = new FileInputStream(name);
			int o_ofs = -1;
			if( modestr != null ) o_ofs = modestr.indexOf('o');
			int ofs = 0;
			if( o_ofs != -1 ) {
				// seek to offset
				StringBuilder builder = new StringBuilder(256);
				int i = o_ofs + 1;
				final int count = modestr.length();
				for( ; i < count; i++ ) {
					int ch = modestr.codePointAt(i);
					if( ch >= '0' && ch <= '9' ) {
						builder.append(ch);
					} else {
						break;
					}
				}
				LexBase lex = new LexBase( builder.toString() );
				Number num = lex.parseNumber();
				if( num != null ) {
					ofs = num.intValue();
					mStream.skip(ofs);
				}
			}
			// check first of the file - whether the file is unicode
			byte[] mark = new byte[2];
			mStream.read( mark );
			if( mark[0] == 0xff && mark[1] == 0xfe ) {
				// unicode
				mDirectLoad = true;
				mReader = new InputStreamReader(mStream, "UTF-16LE");
			} else if( mark[0] == 0xfe && mark[1] == 0xfe ) {
				// ciphered text or compressed
				byte[] mode = new byte[1];
				mStream.read( mode );
				if( mode[0] != 0 && mode[0] != 1 && mode[0] != 2 ) {
					throw new TJSException( /*Error.UnsupportedCipherMode*/ ); // TODO エラーメッセージを作る
				}
				mCryptMode = mode[0];
				boolean directLoad = mCryptMode != 2;
				mStream.read( mark ); // original bom code comes here (is not compressed)
				if(mark[0] != 0xff || mark[1] != 0xfe)
					throw new TJSException( /*Error.UnsupportedCipherMode*/ ); // TODO エラーメッセージを作る

				if( mCryptMode == 2 ) {
					// compressed text stream
					// TODO 圧縮ストリームを展開する機能を実装する

				}
			} else {
				// 開き直してシークする
				mStream.close();
				mStream = new FileInputStream(name);
				mStream.skip(ofs);
				mReader = new InputStreamReader(mStream, "MS932");
			}
		} catch (FileNotFoundException e) {
			if( mStream != null ) {
				try {
					mStream.close();
				} catch (IOException e2) {
					throw new TJSException( Error.ReadError + e2.toString() );
				}
			}
			throw new TJSException( Error.ReadError + e.toString() );
		} catch (IOException e) {
			if( mStream != null ) {
				try {
					mStream.close();
				} catch (IOException e2) {
					throw new TJSException( Error.ReadError + e2.toString() );
				}
			}
			throw new TJSException( Error.ReadError + e.toString() );
		}
	}
	public String read( int size ) throws TJSException {
		if( mStream == null ) return null;
		if( size < 0 ) return null;
		int ret = 0;
		try {

			if( mCryptMode == -1 ) {
				if( size == 0 ) {
					size = mStream.available();
					if( mDirectLoad ) size /= 2;
					if( size <= 0 ) return null;
				}
				char[] cbuf = new char[size];
				ret = mReader.read( cbuf, 0, size );
				if( ret <= 0 ) return null;
				return new String(cbuf,0,ret);
			} else if( mCryptMode == 0 ) {
				// simple crypt
				// TODO 読み込みと復号化処理を書く
			} else if( mCryptMode == 1 ) {
				// simple crypt
				// TODO 読み込みと復号化処理を書く
			}
		} catch (IOException e) {
			throw new TJSException( Error.ReadError + e.toString() );
		}
		//if( ret <= 0 ) return null;
		return null;
	}
	public void close() {
		if( mStream != null ) {
			try {
				mStream.close();
				mStream = null;
			} catch (IOException e) {
			}
		}
	}
	public void destruct() {
		close();
	}
}
