package jp.mydns.masahase.abaqus;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StringWriter;

/**
 * ASCII形式の結果ファイルの読み込み
 * 
 * @author MASA.H
 * @version 1.0
 */
public class ReadAscFil implements IReadFil {
	private transient FileReader r_file;
	private transient boolean btype;
	private transient Object[] rcontents;
	private transient int recordKey;
	private String rfname;

	public ReadAscFil() {
		btype = false;
	}

	public void setFileName(final String fname) throws FileNotFoundException {
		rfname = fname;
		r_file = new FileReader(fname);
		try {
			if (r_file.read() == '*') {
				btype = true;
			} else {
				btype = false;
			}
			rewind();
		} catch (IOException e) {
			e.printStackTrace();
			btype = false;
		}

	}

	public int getNextRecordKey() throws EOFException {
		if (!btype)
			return -1;
		try {
			readNextRecord();
		} catch (IOException e) {
			// 終了レコードの検知
			if (recordKey == 2001) {
				throw new EOFException();
			}else{
				throw new EOFException("Broken?");
			}
		}
		return recordKey;
	}

	public Object[] getRecordContents() {
		if (recordKey == 0)
			return new Object[0];
		Object[] ret = new Object[rcontents.length];
		try {
			final ByteArrayOutputStream bos = new ByteArrayOutputStream();
			final ObjectOutputStream oos = new ObjectOutputStream(bos);
			for (int i = 0; i < rcontents.length; i++) {
				oos.writeObject(rcontents[i]);
			}
			final ObjectInputStream ois = new ObjectInputStream(
					new ByteArrayInputStream(bos.toByteArray()));
			for (int i = 0; i < ret.length; i++) {
				ret[i] = ois.readObject();
			}
		} catch (IOException e) {
			e.printStackTrace();
			ret = new Object[0];
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			ret = new Object[0];
		}
		return ret;
	}

	public void rewind() {
		try {
			r_file.close();
			r_file = new FileReader(rfname);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public boolean isType() {
		if (r_file == null)
			return false;
		return btype;
	}

	private void readNextRecord() throws IOException {
		int cbuf;
		int RecordSize;
		recordKey = -1;
		// レコード�?先�?の探索
		while ((cbuf = r_file.read()) != -1) {
			if (cbuf == '*')
				break;
		}
		if(cbuf==-1){
			throw new EOFException();
		}
		assert cbuf == '*';
		// レコードサイズの取�?
		cbuf = getNextChar();
		assert cbuf == 'I';
		RecordSize = readInteger();
		assert RecordSize >= 2;
		// レコードキーの取�?
		cbuf = getNextChar();
		assert cbuf == 'I';
		recordKey = readInteger();
		assert recordKey != -1;
		// レコード本体�?�?��の解�?
		rcontents = new Object[RecordSize - 2];
		if (rcontents == null) {
			rcontents = new Object[0];
		}
		for (int i = 0; i < RecordSize - 2; i++) {
			cbuf = getNextChar();
			if (cbuf == 'I') {
				rcontents[i] = Integer.valueOf(readInteger());
			} else if (cbuf == 'A') {
				rcontents[i] = readString();
			} else if (cbuf == 'E' || cbuf == 'D') {
				rcontents[i] = Double.valueOf(readFloat());
			}
		}
	}

	/**
	 * ファイルより整数の読み取り
	 */
	private int readInteger() throws IOException {
		StringWriter swbuf = new StringWriter();
		int cbuf, NumLen=0;
		cbuf = getNextChar();
		if (cbuf != ' ')
			swbuf.write(cbuf);
		cbuf = getNextChar();
		assert cbuf != ' ';
		swbuf.write(cbuf);
		try {
			NumLen = (Integer.valueOf(swbuf.toString())).intValue();
		} catch (NumberFormatException e) {
			return -1;
		}
		swbuf.close();
		swbuf = new StringWriter();
		for (int i = 0; i < NumLen; i++) {
			cbuf = getNextChar();
			assert cbuf != ' ';
			swbuf.write(cbuf);
		}
		return Integer.valueOf(swbuf.toString()).intValue();
	}

	/**
	 * ファイルより次の文字��を読み取り
	 */
	private int getNextChar() throws IOException {
		int cbuf = -1;
		while ((cbuf = r_file.read()) != -1) {
			if (cbuf != '\n')
				break;
		}
		return cbuf;
	}

	/**
	 * ファイルより次の文字列もしくはラベル識別子を読み取り
	 * 
	 * @return
	 * @throws IOException
	 */
	private Object readString() throws IOException {
		int cbuf;
		final StringWriter swbuf = new StringWriter();
		cbuf = getNextChar();
		if (cbuf == ' '&&recordKey!=1940) {
			for (int i = 0; i < 7; i++) {
				cbuf = getNextChar();
				if (cbuf != ' ')
					swbuf.write(cbuf);
			}
			try {
				return Integer.valueOf(swbuf.toString());
			} catch (NumberFormatException e) {
				return "";
			}
		} else {
			swbuf.write(cbuf);
			for (int i = 0; i < 7; i++) {
				cbuf = getNextChar();
				swbuf.write(cbuf);
			}
			return swbuf.toString();
		}
	}

	/**
	 * ファイルより次の浮動小数点データの読み取り
	 * 
	 * @return
	 * @throws IOException
	 */
	private double readFloat() throws IOException {
		final StringWriter swbuf = new StringWriter();
		for (int i = 0; i < (18 + 4); i++) {
			swbuf.write(getNextChar());
		}
		assert swbuf.toString().replace('D', 'E') != "";
		return Double.valueOf(swbuf.toString().replace('D', 'E')).doubleValue();
	}
}
