package de.ivu.elect.was.exchange.stimmeingabe.replikation;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;

import javax.annotation.Nonnull;
import javax.ejb.Stateless;
import javax.inject.Inject;

import de.ivu.elect.business.datei.entity.ServerFileType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.datei.control.FileExchange;
import de.ivu.elect.business.datei.control.ImportFileProperties;
import de.ivu.elect.business.datei.entity.DateiImport;
import de.ivu.elect.business.datei.entity.DateiImportBerichtCustomData;
import de.ivu.elect.business.exchange.entity.DateiImportArt;
import de.ivu.elect.business.exchange.entity.ImportStatus;
import de.ivu.elect.business.konfiguration.entity.ElectKonfigurationWerte;
import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.business.stimmeingabe.boundary.StimmeingabeImporter;
import de.ivu.elect.business.stimmeingabe.control.StimmeingabeImportContext;
import de.ivu.elect.business.stimmeingabe.control.replikation.StimmeingabeAutomatischImportieren;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingang;
import de.ivu.elect.business.wahl.boundary.WahlDAO;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.Wahldurchfuehrung;
import de.ivu.elect.jee.exchange.ImportOptions;
import de.ivu.elect.was.exchange.AbstractDateienWahlunabhaengigAutomatischImporteren;
import de.ivu.elect.business.replikation.entity.FileInfo;
import de.ivu.elect.was.exchange.stimmeingabe.WasStimmeingabeXMLZIPImportMapper;


import static de.ivu.elect.business.system.entity.SystemLogQuelle.STIMMEINGABE_DATEIEN_IMPORTER;

/**
 *  on 14.08.2015.
 */
@Stateless
public class ExchangeStimmeingabeAutomatischImportieren extends AbstractDateienWahlunabhaengigAutomatischImporteren implements StimmeingabeAutomatischImportieren {

  private static final Logger LOG = LoggerFactory.getLogger(ExchangeStimmeingabeAutomatischImportieren.class);

  private static final int MAX_ANZAHL_DATEIEN_PER_TRANSACTION = 10;

  private static final String STIMMEINGABE_DATEIEN_IMPORTER_NAME = "Stimmeingabeimporter";

  @Inject
  private transient WasStimmeingabeXMLZIPImportMapper wasStimmeingabeXMLZIPImportMapper;

  @Inject
  private transient WahlDAO wahlDAO;

  @Inject
  private transient StimmeingabeImporter stimmeingabeImporter;

  @Inject
  private transient FileExchange fileExchange;

  @Override
  public boolean isEtwasZuImportieren(Mandant mandant) {
    return isDateiFuerImportVorhanden();
  }

  private void importiereDatei(Wahldurchfuehrung wahldurchfuehrung, File file) throws IOException {

    try (FileInputStream fis = new FileInputStream(file)) {
      ImportFileProperties properties = new ImportFileProperties(file.getName(), wasStimmeingabeXMLZIPImportMapper.getFileFormat(), DateiImportArt.STIMMEINGABE_IMPORT);
      DateiImport dateiImport = fileExchange.createAndPersistDateiImportAndSpeichereDateiAufServer(fis, properties, wahldurchfuehrung.getMandant(), wahldurchfuehrung, new DateiImportBerichtCustomData(), ServerFileType.IMPORTIERTE_DATEI);
      dateiImport.setImportStatus(ImportStatus.FORMAT_FESTGELEGT);
      stimmeingabeImporter.importieren(dateiImport, new StimmeingabeImportContext(wahldurchfuehrung),
          ImportOptions.NEUE_DATEN_ANLEGEN_BESTEHENDE_DATEN_UNVERAENDERT_LASSEN);
    }

  }

  private Wahl findeWahl(Mandant mandant, Wahl wahlInDatei) {
    return wahlDAO.findByAll(mandant).stream()
        .filter(wahl -> wahlenSindGleich(wahl, wahlInDatei))
        .findFirst().orElse(null);
  }

  private boolean wahlenSindGleich(Wahl wahl, Wahl wahlInDatei) {
    return wahl.getWahldatum().equals(wahlInDatei.getWahldatum()) && wahl.getWahlart().getName().equalsIgnoreCase(wahlInDatei.getWahlart().getName());
  }



  @Override
  protected void importiereDatei(Mandant mandant, FileInfo fi) throws Exception {
    File file = fi.getFile();
    List<Ergebniseingang> ergebniseingaenge;
    try (FileInputStream fis = new FileInputStream(file)) {
      ergebniseingaenge = wasStimmeingabeXMLZIPImportMapper.deserialize(fis, null, null);
    }

    if (ergebniseingaenge.isEmpty() || ergebniseingaenge.size() > 1) {
      systemLogWriter.writeErrorLogMessageNewTransaction("Import deaktiviert, Datei enthält keinen oder mehr als einen Ergebniseingang:'" + file.getAbsolutePath() + "'", STIMMEINGABE_DATEIEN_IMPORTER);
      deaktiviereImport();
    }

    Ergebniseingang ergebniseingang = ergebniseingaenge.get(0);

    Long eingangssequenznummerInDatei = ergebniseingang.getEingangssequenznummer();
    Long eingangssequenznummerInDateiname = fi.getSequencenummer();

    if (!eingangssequenznummerInDateiname.equals(eingangssequenznummerInDatei)) {
      systemLogWriter.writeErrorLogMessageNewTransaction("Import deaktiviert, Datei enthält andere Eingangssequenznummer als im Dateinamen hnterlegt: eingangssequenznummerInDatei=" + eingangssequenznummerInDatei + ", eingangssequenznummerInDateiname=" + eingangssequenznummerInDateiname + ", Datei: " + file.getAbsolutePath(), STIMMEINGABE_DATEIEN_IMPORTER);
      deaktiviereImport();
      return;

    }

    Wahl wahlInDatei = ergebniseingang.getWahldurchfuehrungsgebiet().getWahl();

    Wahl wahlInSystem = findeWahl(mandant, wahlInDatei);

    if (wahlInSystem == null) {
      systemLogWriter.writeErrorLogMessageNewTransaction("Import deaktiviert, keine Wahl zu Wahl in Datei gefunden, Datum:" + wahlInDatei.getWahltermin().getWahldatum() + ", Wahlart: " + wahlInDatei.getWahlart().getName(), STIMMEINGABE_DATEIEN_IMPORTER);
      deaktiviereImport();
      return;
    }

    importiereDatei(wahlInSystem.castTo(Wahldurchfuehrung.class).getEntity(), file);
    aktualisiereLetzteSequenznumer(eingangssequenznummerInDatei);

    LOG.info("Datei importiert: " + file.getAbsolutePath());
  }

  @Override
  protected int getMaxAnzahlDateienProTransaktion() {
    return MAX_ANZAHL_DATEIEN_PER_TRANSACTION;
  }

  @Override
  protected Logger getLog() {
    return LOG;
  }


  @Override
  @Nonnull
  protected ElectKonfigurationWerte getVerzeichnisKonfigurationWert() {
    return ElectKonfigurationWerte.STIMMEINGABE_IMPORTVERZEICHNIS;
  }

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

  @Override
  @Nonnull
  protected ElectKonfigurationWerte getLetzteIdKonfigurationWert() {
    return ElectKonfigurationWerte.STIMMEINGABE_IMPORT_EINGANGSSEQUENZNUMMER;
  }

  @Nonnull
  @Override
  protected ElectKonfigurationWerte getCronTabKonfigurationWert() {
    return ElectKonfigurationWerte.STIMMEINGABE_IMPORT_CRONTAB;
  }

  @Override
  protected String getImporterName() {
    return STIMMEINGABE_DATEIEN_IMPORTER_NAME;
  }

}
