package org.teiid.query.parser;

import com.datavirtuality.dv.core.interfaces.RecorderStream;
import org.apache.commons.collections.buffer.CircularFifoBuffer;

import java.io.IOException;
import java.io.Reader;
import java.util.Objects;
import java.util.stream.Collectors;

public class PositionAwareJavaCharStream extends JavaCharStream implements RecorderStream {
	protected int totalCharsRead = 0;
	protected int absoluteTokenBengin = 0;
	private StringBuilder recorded = null;
	private final CircularFifoBuffer buf = new CircularFifoBuffer(256);

	public PositionAwareJavaCharStream(Reader sql) {
		super(sql);
	}

	@Override
	public char BeginToken() throws IOException {
		absoluteTokenBengin = inBuf > 0 ? totalCharsRead - 1 : totalCharsRead;
		return super.BeginToken();
	}

	@Override
	protected void UpdateLineColumn(char c) {
		totalCharsRead++;
		super.UpdateLineColumn(c);
	}

	public final int getAbsoluteTokenBengin() {
	    return absoluteTokenBengin;
	}

	public void startRecord(int start) {
		String initialData = "";
		int bufferStart = totalCharsRead - buf.size();
		if (start < totalCharsRead) {
			if (start < bufferStart)
				start = bufferStart;
			//noinspection unchecked
			initialData = ((String) buf.stream().map(Objects::toString).collect(Collectors.joining())).substring(start - bufferStart);
		}
		recorded = new StringBuilder(initialData);
	}

	public String getRecorded(int end) {
		StringBuilder recorded1 = recorded;
		if (end > totalCharsRead)
			end = totalCharsRead;
		recorded = null;
		int start = totalCharsRead - recorded1.length();
		recorded1.delete(end - start, totalCharsRead - start);
		return recorded1.toString();
	}

	@Override
	public char readChar() throws IOException {
		final char c = super.readChar();
		buf.add(c);
		if (recorded != null)
			recorded.append(c);
		return c;
	}
}
