package com.widen.tabitha;

import com.widen.tabitha.formats.delimited.DelimitedFormat;
import com.widen.tabitha.formats.delimited.DelimitedRowReader;
import com.widen.tabitha.formats.excel.XLSRowReader;
import com.widen.tabitha.formats.excel.XLSXRowReader;
import org.apache.tika.Tika;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;

/**
 * Helper factory methods for creating row readers.
 */
public class RowReaderFactory {
    /**
     * Attempt to detect the format of a file at the given path and open it as a row reader.
     *
     * @param path The file path of the file to open.
     * @return A row reader if the file is in a supported format.
     */
    public static Optional<RowReader> open(String path) throws Exception {
        return open(new File(path), null);
    }

    /**
     * Attempt to detect the format of a file and open it as a row reader.
     *
     * @param file The file to open.
     * @return A row reader if the file is in a supported format.
     */
    public static Optional<RowReader> open(File file) throws Exception {
        return open(file, null);
    }

    /**
     * Attempt to detect the format of a file and open it as a row reader.
     *
     * @param file The file to open.
     * @param options Options to pass to the reader.
     * @return A row reader if the file is in a supported format.
     */
    public static Optional<RowReader> open(File file, ReaderOptions options) throws Exception {
        String mimeType = tika.detect(file);

        switch (mimeType) {
            case "text/csv":
            case "text/plain":
                return Optional.of(decorate(new DelimitedRowReader(new FileInputStream(file), DelimitedFormat.CSV), options));

            case "text/tab-separated-values":
                return Optional.of(decorate(new DelimitedRowReader(new FileInputStream(file), DelimitedFormat.TSV), options));

            case "application/vnd.ms-excel":
                return Optional.of(decorate(XLSRowReader.open(file, options), options));

            case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
            case "application/x-tika-ooxml":
                return Optional.of(decorate(XLSXRowReader.open(file, options), options));
        }

        return Optional.empty();
    }

    /**
     * Attempt to detect the format of an input stream and open it as a row reader.
     *
     * @param inputStream The input stream to read.
     * @return A row reader if the stream is in a supported format.
     */
    public static Optional<RowReader> open(InputStream inputStream) throws IOException {
        return open(inputStream, null, null);
    }

    /**
     * Attempt to detect the format of an input stream and open it as a row reader.
     *
     * @param inputStream The input stream to read.
     * @param filename The filename associated with the stream, if known.
     * @return A row reader if the stream is in a supported format.
     */
    public static Optional<RowReader> open(InputStream inputStream, String filename) throws IOException {
        return open(inputStream, filename, null);
    }

    /**
     * Attempt to detect the format of an input stream and open it as a row reader.
     *
     * @param inputStream The input stream to read.
     * @param options Options to pass to the reader.
     * @return A row reader if the stream is in a supported format.
     */
    public static Optional<RowReader> open(InputStream inputStream, ReaderOptions options) throws IOException {
        return open(inputStream, null, options);
    }

    /**
     * Attempt to detect the format of an input stream and open it as a row reader.
     *
     * @param inputStream The input stream to read.
     * @param filename The filename associated with the stream, if known.
     * @param options Options to pass to the reader.
     * @return A row reader if the stream is in a supported format.
     */
    public static Optional<RowReader> open(
        InputStream inputStream,
        String filename,
        ReaderOptions options
    ) throws IOException {
        String mimeType = tika.detect(inputStream, filename);

        switch (mimeType) {
            case "text/csv":
            case "text/plain":
                return Optional.of(decorate(new DelimitedRowReader(inputStream, DelimitedFormat.CSV), options));

            case "text/tab-separated-values":
                return Optional.of(decorate(new DelimitedRowReader(inputStream, DelimitedFormat.TSV), options));

            case "application/vnd.ms-excel":
                return Optional.of(decorate(XLSRowReader.open(inputStream, options), options));

            case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
            case "application/x-tika-ooxml":
                return Optional.of(decorate(XLSXRowReader.open(inputStream, options), options));
        }

        return Optional.empty();
    }

    private static RowReader decorate(RowReader reader, ReaderOptions options) {
        if (options != null && options.isInlineHeaders()) {
            reader = new InlineHeaderReader(reader);
        }
        return reader;
    }

    // Apache Tika instance for detecting MIME types.
    private static final Tika tika = new Tika();
}

@@ -1527,32 +1527,117 @@
 ows Exception %7B%0A
+        if (options == null) %7B%0A            options = new ReaderOptions();%0A        %7D%0A%0A
         String m
@@ -4249,32 +4249,117 @@
 s IOException %7B%0A
+        if (options == null) %7B%0A            options = new ReaderOptions();%0A        %7D%0A%0A
         String m
@@ -5292,27 +5292,8 @@
 ions
- != null && options
 .isI

Use default reader options if null