package com.widen.tabitha;

import com.widen.tabitha.formats.delimited.DelimitedRowReader;
import com.widen.tabitha.formats.delimited.DelimitedFormat;
import com.widen.tabitha.formats.excel.WorkbookRowReader;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
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.
     *
     * @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));
    }

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

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

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

            case "application/vnd.ms-excel":
                try {
                    return Optional.of(new WorkbookRowReader(file));
                } catch (InvalidFormatException e) {
                    break;
                }

            case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
            case "application/x-tika-ooxml":
                return Optional.of(new WorkbookRowReader(file));
        }

        return Optional.empty();
    }

    /**
     * Attempt to detect the format of an input stream and open it as a row reader.
     *
     * @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);
    }

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

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

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

            case "application/vnd.ms-excel":
            case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
            case "application/x-tika-ooxml":
                try {
                    return Optional.of(new WorkbookRowReader(inputStream));
                } catch (InvalidFormatException e) {
                    break;
                }
        }

        return Optional.empty();
    }

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

@@ -198,24 +198,131 @@
 kRowReader;%0A
+import com.widen.tabitha.formats.excel.XLSRowReader;%0Aimport com.widen.tabitha.formats.excel.XLSXRowReader;%0A
 import org.a
@@ -372,24 +372,24 @@
 tException;%0A
-
 import org.a
@@ -1620,34 +1620,8 @@
 l%22:%0A
-                try %7B%0A    
     
@@ -1647,36 +1647,27 @@
 Optional.of(
-new Workbook
+XLS
 RowReader(fi
@@ -1659,32 +1659,37 @@
 XLSRowReader
+.open
 (file));
 %0A           
@@ -1680,106 +1680,8 @@
 e));
-%0A                %7D catch (InvalidFormatException e) %7B%0A                    break;%0A                %7D
 %0A%0A  
@@ -1840,36 +1840,28 @@
 Optional.of(
-new Workbook
+XLSX
 RowReader(fi
@@ -1857,16 +1857,21 @@
 owReader
+.open
 (file));
@@ -2938,32 +2938,101 @@
 /vnd.ms-excel%22:%0A
+                return Optional.of(XLSRowReader.open(inputStream));%0A%0A
             case
@@ -3150,34 +3150,8 @@
 l%22:%0A
-                try %7B%0A    
     
@@ -3185,20 +3185,12 @@
 .of(
-new Workbook
+XLSX
 RowR
@@ -3186,32 +3186,37 @@
 of(XLSXRowReader
+.open
 (inputStream));%0A
@@ -3219,106 +3219,8 @@
 ));%0A
-                %7D catch (InvalidFormatException e) %7B%0A                    break;%0A                %7D%0A
     

Use new Excel readers in factory