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

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;

import java.io.InputStream;

/**
 * @author avhaliullin
 */
public interface YtTableReadDriver<T> {
    OutputFormat getFormat();

    InterruptableIterator<T> createParser(InputStream in);

    static <T> YtTableReadDriver<T> createDSVDriver(YtRowMapper<T> rowMapper, YtMissingValueMode missingValueMode) {
        OutputFormat format = OutputFormat.createSchemafulDsv(rowMapper.getColumns(), missingValueMode);
        return new YtTableReadDriver<T>() {
            @Override
            public OutputFormat getFormat() {
                return format;
            }

            @Override
            public InterruptableIterator<T> createParser(InputStream in) {
                return new SchemafulDsvParser2<T>(in, rowMapper);
            }
        };
    }

    static <T> YtTableReadDriver<T> createYSONDriver(Class<T> valueClass) {
        return createYSONDriver(valueClass, YtService.OM);
    }

    static <T> YtTableReadDriver<T> createYSONDriver(Class<T> valueClass, ObjectMapper om) {
        return new YsonDriver<>(OutputFormat.createBinaryYson(), om.readerFor(valueClass));
    }

    static <T> YtTableReadDriver<T> createYSONDriver(TypeReference<T> valueType) {
        return createYSONDriver(valueType, YtService.OM);
    }

    static <T> YtTableReadDriver<T> createYSONDriver(TypeReference<T> valueType, ObjectMapper om) {
        return new YsonDriver<>(OutputFormat.createBinaryYson(), om.readerFor(valueType));
    }

    class YsonDriver<T> implements YtTableReadDriver<T> {
        private final OutputFormat format;
        private final ObjectReader objectReader;

        private YsonDriver(OutputFormat format, ObjectReader objectReader) {
            this.format = format;
            this.objectReader = objectReader;
        }

        @Override
        public OutputFormat getFormat() {
            return format;
        }

        @Override
        public InterruptableIterator<T> createParser(InputStream in) {
            return new YsonTableParser<>(in, objectReader);
        }
    }
}
