
package de.ivu.elect.exchange.csv;

import static java.util.Objects.nonNull;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jsefa.common.converter.SimpleTypeConverter;

import de.ivu.elect.business.datei.entity.CsvZeichensatz;
import de.ivu.elect.business.exchange.control.CsvFileKonfiguration;
import de.ivu.elect.business.exchange.control.FileKonfiguration;

public class CsvDescriptor {

  private boolean withHeader;

  private List<String> header;

  private final CsvFileKonfiguration csvFileKonfiguration;

  private final Map<Class< ? >, Class< ? extends SimpleTypeConverter>> converterTypePerObjectType = new HashMap<>();

  private CsvDescriptor(FileKonfiguration fileKonfiguration) {
    super();

    requireCsvFileKonfiguration(fileKonfiguration);

    this.csvFileKonfiguration = (CsvFileKonfiguration) fileKonfiguration;
  }

  public CsvZeichensatz getCsvZeichensatz() {
    if (nonNull(csvFileKonfiguration.getZeichensatz())) {
      return csvFileKonfiguration.getZeichensatz();
    }

    return CsvZeichensatz.UTF_8;
  }

  public boolean isWithHeader() {
    return withHeader;
  }

  public void setSimpleTypeConverterMapping(Class< ? > objectType, Class< ? extends SimpleTypeConverter> converterType) {
    converterTypePerObjectType.put(objectType, converterType);
  }

  public Map<Class< ? >, Class< ? extends SimpleTypeConverter>> getSimpleTypeConverterMapping() {
    return converterTypePerObjectType;
  }

  public void setWithHeader(boolean withHeader) {
    this.withHeader = withHeader;
  }

  public List<String> getHeader() {
    return header;
  }

  private void setHeader(List<String> header) {
    this.header = header;
  }

  public CsvFileKonfiguration getCsvFileKonfiguration() {
    return csvFileKonfiguration;
  }

  public static List<String> createHeaderForClass(Class< ? > dtoClass) {
    return new ElectCsvHeaderExtractor().extractHeader(dtoClass);
  }

  public static CsvDescriptor withHeader(FileKonfiguration fileKonfiguration, Class< ? > dtoClass) {
    return withHeader(fileKonfiguration, createHeaderForClass(dtoClass));
  }

  public static CsvDescriptor withHeader(FileKonfiguration fileKonfiguration, List<String> headers) {
    CsvDescriptor result = new CsvDescriptor(fileKonfiguration);
    result.setWithHeader(true);
    result.setHeader(headers);
    return result;
  }

  public static CsvDescriptor noHeader(FileKonfiguration fileKonfiguration) {
    CsvDescriptor result = new CsvDescriptor(fileKonfiguration);
    result.setWithHeader(false);
    return result;
  }

  public static CsvDescriptor forFileKonfiguration(FileKonfiguration fileKonfiguration) {
    CsvDescriptor result = new CsvDescriptor(fileKonfiguration);
    result.setWithHeader(isWithHeaderFromAnzahlKopfzeilen(result));
    return result;
  }

  private static boolean isWithHeaderFromAnzahlKopfzeilen(CsvDescriptor result) {
    Long anzahlKopfzeilen = result.getCsvFileKonfiguration().getAnzahlKopfzeilen();

    if (anzahlKopfzeilen == null) {
      return false;
    }

    return anzahlKopfzeilen.intValue() != 0;
  }

  private void requireCsvFileKonfiguration(FileKonfiguration fileKonfiguration) {
    if (!(fileKonfiguration instanceof CsvFileKonfiguration)) {
      throw new IllegalArgumentException("Es konnte keine Konfiguration der Einstellungen der CSV-Datei gefunden werden! [fileKonfiguration = " + fileKonfiguration + "]");
    }
  }
}
