package de.ivu.elect.core.exchange.stimmen.csv.dynamic;

import java.io.OutputStream;
import java.util.List;
import java.util.stream.Collectors;

import org.jsefa.csv.CsvSerializer;

import de.ivu.elect.business.datei.entity.FileType;
import de.ivu.elect.business.ergebnis.control.ErgebnisDaten;
import de.ivu.elect.business.exchange.control.FileFormat;
import de.ivu.elect.business.gebietsbaum.control.GebietByBreadthFirstComparator;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.exchange.csv.raw.AbstractRawCsvExportMapper;
import de.ivu.elect.was.exchange.ergebnis.ErgebnisExportMapper;

public abstract class AbstractDynamicStimmenExportMapper<F extends AbstractDynamicStimmenExportDTOFactory> extends AbstractRawCsvExportMapper implements ErgebnisExportMapper {

  private static final long serialVersionUID = -1734493049835717305L;

  protected abstract F createDtoFactory(Wahldurchfuehrungsgebiet wurzelgebiet, ErgebnisDaten ergebnisDaten);

  @Override
  protected boolean closeOutputStreamOnCloseSerializer() {
    return true;
  }

  @Override
  public FileFormat getFileFormat() {
    return new FileFormat(getFileFormatName(), getFileType());
  }

  protected abstract FileType getFileType();

  protected void writeDatenFuerWurzelgebiet(OutputStream os, ErgebnisDaten ergebnisDaten, Wahldurchfuehrungsgebiet wurzelgebiet) {
    F factory = createDtoFactory(wurzelgebiet, ergebnisDaten);
    List<List<String>> headers = factory.createHeader();

    CsvSerializer serializer = openSerializer(os);
    try {

      for (List<String> header : headers) {
        serializer.writeHeader(header);
      }

      List<Gebiet> collect = ergebnisDaten.getErfassteGebiete().stream()
          .filter(wurzelgebiet::isInGebietshierarchieUebergeordnetesGebietVon)
          .sorted(new GebietByBreadthFirstComparator()).collect(Collectors.toList());

      for (Gebiet gebiet : collect) {
        Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = gebiet.castTo(Wahldurchfuehrungsgebiet.class).getEntity();

        serializer.writeHeader(factory.schreibeDaten(wahldurchfuehrungsgebiet));

      }

    } finally {
      closeSerializer(serializer);
    }
  }
}
