package sharin.csv.parser;

import java.io.Reader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import sharin.util.IoUtils;

class BasicCsvIterator implements Iterator<String[]>, CsvHandler {

    private static final int START = 0;

    private static final int END_RECORD = 1;

    private static final int END_DOCUMENT = 2;

    private final Reader reader;

    private final BasicCsvAutomaton automaton;

    private List<String> valueList;

    private StringBuilder valueBuilder;

    private int state;

    private String[] record;

    public BasicCsvIterator(Reader reader, char separator) {
        this.reader = reader;
        this.automaton = new BasicCsvAutomaton(this, separator);
        state = START;
    }

    public boolean hasNext() {
        record = nextRecord();
        return record != null;
    }

    public String[] next() {
        return record;
    }

    public void remove() {
        throw new UnsupportedOperationException();
    }

    private String[] nextRecord() {

        if (state == END_DOCUMENT) {
            return null;
        }

        valueList = null;
        valueBuilder = null;
        state = START;

        while (true) {
            automaton.put(IoUtils.read(reader));

            if (state != START) {
                break;
            }
        }

        if (valueList == null) {
            return null;
        }

        return valueList.toArray(new String[valueList.size()]);
    }

    public void startDocument() {
        /* do nothing */
    }

    public void startRecord() {
        valueList = new ArrayList<String>();
    }

    public void startValue() {
        valueBuilder = new StringBuilder();
    }

    public void character(char ch) {
        valueBuilder.append(ch);
    }

    public void endValue() {
        valueList.add(valueBuilder.toString());
        valueBuilder = null;
    }

    public void endRecord() {
        state = END_RECORD;
    }

    public void endDocument() {
        state = END_DOCUMENT;
    }
}