
package de.ivu.elect.was.exchange.ergebnis.eml;

import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Nullable;
import javax.inject.Inject;

import de.ivu.elect.business.datei.entity.FileType;
import de.ivu.elect.business.ergebnis.control.ErgebnisDaten;
import de.ivu.elect.business.ergebnis.control.ErgebnisExportContext;
import de.ivu.elect.business.ergebnis.control.ErgebnisExportObject;
import de.ivu.elect.business.ergebnis.entity.Ergebnisart;
import de.ivu.elect.business.gebietsbaum.boundary.GebietDAO;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.gruppe.entity.NlPolitischeGruppe;
import de.ivu.elect.business.kandidatur.entity.Listenkandidatur;
import de.ivu.elect.business.stimmeingabe.boundary.NlVoteType;
import de.ivu.elect.business.stimmeingabe.control.NlStimmeingabeKopfzahlKonfiguration;
import de.ivu.elect.business.wahl.entity.NlWahlart;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahlvorschlag.boundary.WahlvorschlagDAO;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.nl.eml.readable.GroupVotesSection;
import de.ivu.elect.nl.eml.readable.IdShortCode;
import de.ivu.elect.nl.eml.readable.VoteType;

public abstract class Abstract510EmptyErgebnisExportMapper extends Abstract510ErgebnisExportMapper {

  private transient final BigInteger EMPTY_VOTE = BigInteger.ZERO; // empty = filled with zero ELECTVAPP-429

  private static final long serialVersionUID = 1L;

  public static final FileType FILE_FORMAT_TYPE = FileType.ZIP;

  @Inject
  private transient NlStimmeingabeKopfzahlKonfiguration nlStimmeingabeKopfzahlKonfiguration;

  @Inject
  private transient GebietDAO gebietDAO;

  @Inject
  private transient WahlvorschlagDAO wahlvorschlagDAO;

  public Abstract510EmptyErgebnisExportMapper() {
    super();
  }

  @Override
  protected void fillVotes(EmlVotes emlVotes, Wahldurchfuehrungsgebiet gebiet, ErgebnisDaten ergebnisDaten, Map<Gruppe, Liste> listenNachGruppe, Map<Gruppe, Long> positionenDerGruppe) {
    for (Entry<Gruppe, Long> entry : positionenDerGruppe.entrySet()) {
      Gruppe gruppe = entry.getKey();
      Long position = entry.getValue();
      GroupVotesSection groupVotesSection = new GroupVotesSection(Long.toString(position), gruppe.getName(), EMPTY_VOTE,
          new NlPolitischeGruppe(gruppe).isBlancoListe());
      Map<IdShortCode, BigInteger> kandidatenStimmen = emlVotes.getGroupVotes(groupVotesSection);

      Liste liste = listenNachGruppe.get(gruppe);
      List<Listenkandidatur> listenkandidaturenAufStimmzettelSortiertNachPosition = liste.getListenkandidaturenAufStimmzettelSortiertNachPosition(
          ergebnisDaten.getEntityAufStimmzettelDaten());

      for (Listenkandidatur listenkandidatur : listenkandidaturenAufStimmzettelSortiertNachPosition) {
        kandidatenStimmen.put(getKandidatId(listenkandidatur, ergebnisDaten.getEntityAufStimmzettelDaten()), EMPTY_VOTE);
      }
    }

    Map<VoteType, BigInteger> validVotes = emlVotes.getValidVotes();
    for (NlVoteType value : NlVoteType.values()) {
      if (value.isMussErfasstWerden(nlStimmeingabeKopfzahlKonfiguration, gebiet, Ergebnisart.ENDGUELTIG)) {
        validVotes.put(VoteType.valueOf(value.name()), EMPTY_VOTE);
      }
    }
  }

  @Override
  protected List<Wahldurchfuehrungsgebiet> bestimmeReportingUnitGebiete(ErgebnisExportObject ergebnisExportObject, ErgebnisExportContext context) {
    return ergebnisExportObject.getErgebnisDaten().getErfassungsgebiete();
  }

  @Nullable
  @Override
  protected Wahldurchfuehrungsgebiet bestimmeTotalVotesGebiet(ErgebnisExportObject ergebnisExportObject, ErgebnisExportContext context) {
    return ergebnisExportObject.getErgebnisDaten().getWurzelgebiet();
  }

  @Nullable
  @Override
  protected Wahldurchfuehrungsgebiet bestimmeGebietFuerDaten(ErgebnisExportObject ergebnisExportObject, ErgebnisExportContext context) {
    return ergebnisExportObject.getErgebnisDaten().getWurzelgebiet();
  }

  @Override
  protected boolean isGebietAuswahlNotwendig() {
    return false;
  }

  @Override
  protected boolean isErfassungsgebietAuswahlNotwendig() {
    return false;
  }

  @Override
  protected boolean isErgebnisNotwendig() {
    return false; // jederzeit möglich
  }

  @Override
  public boolean isSignEml(Wahl wahl) {
    return false;
  }

  @Override
  protected boolean isWahlebenePassend(Wahl wahl) {
    // ELECTVAPP-305 immer niedrigstes Level nehmen
    boolean isGSB = NlWahlart.isWasGSB(wahl, getCustomer());
    boolean isHSB = NlWahlart.isWasHSB(wahl, getCustomer());
    boolean isCSB = NlWahlart.isWasCSB(wahl, getCustomer());

    if (isCsbNotwendig() && (!isCSB || isHSB || isGSB)) {
      return false;
    }

    if (isHsbNotwendig() && (!isHSB || isGSB)) {
      return false;
    }

    if (isGsbNotwendig() && !isGSB) {
      return false;
    }

    return true;
  }

  @Override
  public boolean isAcceptContext(ErgebnisExportContext context) {
    return super.isAcceptContext(context) && isErfassungsgebieteVorhanden(context) && isWahlvorschlaegeVorhanden(context);
  }

  protected boolean isWahlvorschlaegeVorhanden(ErgebnisExportContext context) {
    return wahlvorschlagDAO.findByCountWahlvorschlagByWahl(context.getWahl()) > 0; // ELECTVAPP-588
  }

  protected boolean isErfassungsgebieteVorhanden(ErgebnisExportContext context) {
    return gebietDAO.findByCountErfassungsgebieteByWahl(context.getWahl()) > 0; // ELECTVAPP-588
  }

  @Override
  protected String createSimpleFileName(ErgebnisExportObject ergebnisExportObject, ErgebnisExportContext context) {
    return super.createSimpleFileName(ergebnisExportObject, context) + "_leeg";
  }
}
