package ru.yandex.webmaster3.storage.util.yt;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.ObjectReader;
import org.apache.commons.io.IOUtils;
import ru.yandex.webmaster3.core.util.JsonStreamUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.NoSuchElementException;

/**
 * @author avhaliullin
 */
public class YsonTableParser<T> implements InterruptableIterator<T> {
    private final InputStream in;
    private final ObjectReader objectReader;

    private JsonParser parser;
    private T next;
    private boolean finished = false;
    private long rowIdx = -1;

    public YsonTableParser(InputStream in, ObjectReader objectReader) {
        this.in = in;
        this.objectReader = objectReader;
    }

    private void resolveParser() throws IOException {
        if (parser == null) {
            parser = YtService.YSON_OM.getFactory().createParser(in);
        }
    }

    @Override
    public boolean hasNext() throws InterruptedException, IOException, YtException {
        if (next != null) {
            return true;
        }
        if (finished) {
            return false;
        }
        resolveParser();
        if (JsonStreamUtils.nextTokenAssertTypeIn(parser, JsonToken.START_OBJECT, null) == JsonToken.START_OBJECT) {
            next = objectReader.readValue(parser);
            return true;
        } else {
            finished = true;
            return false;
        }
    }

    @Override
    public T next() throws InterruptedException, IOException, YtException {
        if (hasNext()) {
            rowIdx++;
            T res = next;
            next = null;
            return res;
        } else {
            throw new NoSuchElementException();
        }
    }

    @Override
    public long getRow() {
        return rowIdx;
    }

    @Override
    public void close() throws IOException {
        finished = true;
        IOUtils.closeQuietly(parser);
        IOUtils.closeQuietly(in);
    }
}
