package ru.yandex.webmaster3.core.download;

import ru.yandex.webmaster3.core.download.searchquery.AbstractWriter;
import ru.yandex.webmaster3.core.download.searchquery.CsvWriter;
import ru.yandex.webmaster3.core.download.searchquery.ExcelWriter;

import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * Created by ifilippov5 on 02.02.17.
 */
public enum FileFormat {
    CSV(".csv", (value) -> String.format(Locale.ROOT, "%.2f", value), CsvWriter::new) {
        @Override
        public <T> byte[] export(List<T> samples, Class<T> clazz) throws IOException {
            return ExportUtil.exportToCsv(samples, clazz);
        }
    },
    /**
     * Используем Locale.FRANCE, чтобы в качестве разделителя между целой частью и дробной
     * была ',' вместо '.'. Иначе excel может конвертировать вещественное число в дату.
     */
    EXCEL(".xlsx", (value) -> String.format(Locale.FRANCE, "%.2f", value), ExcelWriter::new) {
        @Override
        public <T> byte[] export(List<T> samples, Class<T> clazz) throws IOException {
            return ExportUtil.exportToXlsx(samples, clazz);
        }
    },
    CSV_GZ(".csv.gz", null, null) {
        @Override
        public <T> byte[] export(List<T> samples, Class<T> clazz) throws IOException {
            throw new RuntimeException("Not supported!");
        }
    },
    TSV_GZ(".tsv.gz", null, null) {
        @Override
        public <T> byte[] export(List<T> samples, Class<T> clazz) throws IOException {
            throw new RuntimeException("Not supported!");
        }
    },
    ;

    private final String extension;
    private final Function<Double, String> doubleFormatter;
    private final Supplier<AbstractWriter> writerSupplier;

    FileFormat(String extension, Function<Double, String> doubleFormatter, Supplier<AbstractWriter> writerSupplier) {
        this.extension = extension;
        this.doubleFormatter = doubleFormatter;
        this.writerSupplier = writerSupplier;
    }

    public abstract <T> byte[] export(List<T> samples, Class<T> clazz) throws IOException;

    public String getExtension() {
        return extension;
    }

    public Function<Double, String> getDoubleFormatter() {
        return doubleFormatter;
    }

    public AbstractWriter getWriter() {
        return writerSupplier.get();
    }
}
