/*
 * Copyright 2013 Yuichiro Moriguchi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.morilib.awk.nano.io;

import java.io.FilterReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

/**
 * awkの入力を読み込むためのReaderです。
 *
 *
 * @author MORIGUCHI, Yuichiro 2013/03/23
 */
public class AwkReader extends FilterReader implements RecordReader {

	private static enum S1 { INIT, NL }

	//
	private int before = -1;

	/**
	 * AwkReaderを生成します。
	 * 
	 * @param in ラップするInputStream
	 */
	public AwkReader(InputStream in) {
		super(new InputStreamReader(in));
	}

	/**
	 * AwkReaderを生成します。
	 * 
	 * @param in ラップするReader
	 */
	public AwkReader(Reader in) {
		super(in);
	}

	/* (non-Javadoc)
	 * @see java.io.FilterReader#read()
	 */
	public int read() throws IOException {
		int c;

		if(before >= 0) {
			c = before;  before = -1;
			return c;
		} else if((c = super.read()) != '\r') {
			return c;
		} else if((c = super.read()) == '\n') {
			return '\n';
		} else {
			before = c;
			return '\r';
		}
	}

	//
	String readMultiLine() throws IOException {
		StringBuffer b = new StringBuffer();
		S1 stat = S1.INIT;
		int c;

		while(true) {
			if((c = read()) < 0) {
				return b.length() > 0 ? b.toString() : null;
			} else if(c != '\n') {
				if(stat.equals(S1.NL))  b.append('\n');
				b.appendCodePoint(c);
				stat = S1.INIT;
			} else if(stat.equals(S1.NL)) {
				return b.toString();
			} else {
				stat = S1.NL;
			}
		}
	}

	//
	String readr(String rs) throws IOException {
		StringBuffer b = new StringBuffer();
		int c;

		while((c = read()) >= 0 && rs.indexOf(c) < 0) {
			b.appendCodePoint(c);
		}
		return c >= 0 || b.length() > 0 ? b.toString() : null;
	}

	/**
	 * 入力から1レコード読み込みます。
	 * 
	 * @param rs
	 * @return
	 * @throws IOException
	 */
	public String readRecord(String rs) throws IOException {
		return rs.equals("") ? readMultiLine() : readr(rs);
	}

}
