
package de.ivu.elect.exchange.benutzer.csv;

import de.ivu.elect.business.benutzerverwaltung.control.BenutzerExchangeContext;
import de.ivu.elect.business.benutzerverwaltung.entity.Benutzer;
import de.ivu.elect.business.datei.entity.*;
import de.ivu.elect.business.exchange.control.CsvFileKonfiguration;
import de.ivu.elect.business.exchange.control.FileFormat;
import de.ivu.elect.business.exchange.control.FileKonfiguration;
import de.ivu.elect.exchange.CsvImportMapper;
import de.ivu.elect.exchange.benutzer.AbstractDefaultBenutzerMapper;
import de.ivu.elect.exchange.csv.CsvMarshaller;
import de.ivu.elect.jee.exchange.Violations;

import javax.inject.Inject;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

public class DefaultBenutzerCsvMapper extends AbstractDefaultBenutzerMapper<DefaultBenutzerCsvDTO> implements CsvImportMapper<List<Benutzer>, BenutzerExchangeContext> {

  @Inject
  protected transient CsvMarshaller csvMarshaller;

  public DefaultBenutzerCsvMapper() {
    super();
  }

  @Override
  protected DefaultBenutzerCsvDTO createBenutzer() {
    return new DefaultBenutzerCsvDTO();
  }

  @Override
  public boolean isAcceptContext(BenutzerExchangeContext context) {
    return true;
  }

  @Override
  public FileFormat getFileFormat() {
    return new FileFormat(FILE_FORMAT_NAME, FileType.CSV);
  }

  @Override
  public List<String> getCsvColumnHeaders(BenutzerExchangeContext context) {
    return csvMarshaller.extractHeader(DefaultBenutzerCsvDTO.class);
  }

  @Override
  public void serialize(List<Benutzer> object, OutputStream os, BenutzerExchangeContext context, FileKonfiguration fileKonfiguration) {
    CsvFileKonfiguration csvFileKonfigurationWithHeader = addHeaderToFileKonfiguration((CsvFileKonfiguration) fileKonfiguration);
    csvMarshaller.serialize(DefaultBenutzerCsvDTO.class, mappeBenutzerInternToExtern(object), os, csvFileKonfigurationWithHeader);
  }

  @Override
  public List<Benutzer> deserialize(InputStream is, BenutzerExchangeContext context, FileKonfiguration fileKonfiguration) {
    return mappeBenutzerExternToIntern(csvMarshaller.deserialize(DefaultBenutzerCsvDTO.class, is, fileKonfiguration));
  }

  @Override
  public Violations validateInputFormat(InputStream is, BenutzerExchangeContext context, FileKonfiguration fileKonfiguration) {
    return new Violations();
  }

  protected List<DefaultBenutzerCsvDTO> mappeBenutzerInternToExtern(List<Benutzer> benutzerListe) {
    List<DefaultBenutzerCsvDTO> mappedBenutzer = new ArrayList<>(benutzerListe.size());

    for (Benutzer benutzer : benutzerListe) {
      mappedBenutzer.add(mappeBenutzer(benutzer));
    }

    return mappedBenutzer;
  }

  protected List<Benutzer> mappeBenutzerExternToIntern(List<DefaultBenutzerCsvDTO> benutzerListe) {
    List<Benutzer> mappedBenutzer = new ArrayList<>(benutzerListe.size());

    for (DefaultBenutzerCsvDTO benutzer : benutzerListe) {
      mappedBenutzer.add(mappeBenutzer(benutzer));
    }

    return mappedBenutzer;
  }

  private CsvFileKonfiguration addHeaderToFileKonfiguration(CsvFileKonfiguration csvFileKonfiguration) {
    return new CsvFileKonfiguration() {
      @Override
      public CsvZeichensatz getZeichensatz() {
        return csvFileKonfiguration.getZeichensatz();
      }

      @Override
      public Boolean isWithHeader() {
        return true;
      }

      @Override
      public Long getAnzahlKopfzeilen() {
        if (csvFileKonfiguration.getAnzahlKopfzeilen() > 0L) {
          return csvFileKonfiguration.getAnzahlKopfzeilen(); // Fallback, falls Default-Konfiguration irgendwann mal mehr als eine Headerzeile bekommen sollte
        }
        return 1L;
      }

      @Override
      public CsvTrennzeichen getTrennzeichen() {
        return csvFileKonfiguration.getTrennzeichen();
      }

      @Override
      public Boolean isNutzeTrennzeichenNachLetztemFeld() {
        return csvFileKonfiguration.isNutzeTrennzeichenNachLetztemFeld();
      }

      @Override
      public CsvAnfuehrungszeichen getAnfuehrungszeichen() {
        return csvFileKonfiguration.getAnfuehrungszeichen();
      }

      @Override
      public CsvMaskierungszeichen getMaskierungszeichen() {
        return csvFileKonfiguration.getMaskierungszeichen();
      }

      @Override
      public FileFormat getFileFormat() {
        return csvFileKonfiguration.getFileFormat();
      }
    };
  }
}
