
package de.ivu.elect.presentation.gruppeimgebiet.status;

import static java.util.stream.Collectors.toList;

import java.util.Comparator;
import java.util.List;

import javax.inject.Inject;

import de.ivu.elect.business.ergebnis.control.StimmenPoolExtendedDAOFactory;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gruppeimgebiet.control.GruppeImGebietReihenfolgeVorsortierer;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebiet;
import de.ivu.elect.business.kandidatur.control.StimmzettelFormatter;
import de.ivu.elect.business.stimmzettel.boundary.EntityAufStimmzettelDatenStimmzettelPositionBerechnung;
import de.ivu.elect.business.stimmzettel.boundary.EntityAufStimmzettelDatenVorgeladenFactory;
import de.ivu.elect.business.stimmzettel.boundary.StimmzettelGebietErmittler;
import de.ivu.elect.business.stimmzettel.entity.EntityAufStimmzettelDaten;
import de.ivu.elect.business.wahl.entity.WahlParameterExtendedLoader;
import de.ivu.elect.business.wahlvorschlag.entity.Wahlvorschlag;
import de.ivu.elect.jee.presentation.status.OutputSeverity;
import de.ivu.elect.presentation.gebietsbaum.status.GebietsbaumStatusEntry;
import de.ivu.elect.presentation.pruefung.ZulassungPrueferRequestScope;
import de.ivu.elect.presentation.status.AbstractStatusEntryFactory;
import de.ivu.elect.presentation.wahlvorschlag.WahlvorschlagRequestCache;

public class GruppeImGebietStatusEntryFactory extends AbstractStatusEntryFactory {

  private static final long serialVersionUID = 1L;

  @Inject
  protected transient StimmzettelGebietErmittler stimmzettelGebietErmittler;

  @Inject
  protected transient WahlvorschlagRequestCache wahlvorschlagRequestCache;

  @Inject
  protected transient ZulassungPrueferRequestScope zulassungPrueferRequestScope;

  @Inject
  protected transient WahlParameterExtendedLoader wahlParameterExtendedLoader;

  @Inject
  protected transient StimmzettelFormatter stimmzettelFormatter;

  @Inject
  protected transient EntityAufStimmzettelDatenStimmzettelPositionBerechnung entityAufStimmzettelDatenStimmzettelPositionBerechnung;

  @Inject
  protected transient StimmenPoolExtendedDAOFactory stimmenPoolExtendedDAOFactory;

  @Inject
  protected transient GruppeImGebietReihenfolgeVorsortierer gruppeImGebietReihenfolgeVorsortierer;

  public GruppeImGebietStatusEntryFactory() {
    super();
  }

  public GebietsbaumStatusEntry create(Gebiet gebiet, List<GruppeImGebiet> gruppenImGebiet) {
    GebietsbaumStatusEntry gebietsbaumStatusEntry = new GebietsbaumStatusEntry( gebiet, getGebietNummerFormatter());

    OutputSeverity outputSeverity = OutputSeverity.EMPTY;

    for (GruppeImGebiet gruppeImGebiet : gruppenImGebiet) {
      if (!gruppeImGebiet.isRelativePositionGesetzt()) {
        gebietsbaumStatusEntry.addTooltipInformation(getMessage("gruppe.im.gebiet.status.message.positionen.nicht.festgelegt"));

        outputSeverity = OutputSeverity.ERROR;

        break;
      }
    }

    if (stimmzettelGebietErmittler.isStimmzettelGebietOderDarunter(gebiet, wahlvorschlagRequestCache::getAlleWahlvorschlaege)) {
      if (reihenfolgeRelativePositionWeichtVonStimmzettelPositionAb(gebiet, gruppenImGebiet)) {
        gebietsbaumStatusEntry.addTooltipInformation(getMessage("gruppe.im.gebiet.status.message.positionen.weichen.von.stimmzettel.position.ab"));

        if (!outputSeverity.isError()) {
          outputSeverity = OutputSeverity.WARN;
        }
      }
    }

    if (outputSeverity.isEmpty()) {
      outputSeverity = OutputSeverity.SUCCESS;
    }

    gebietsbaumStatusEntry.setSeverity(outputSeverity);

    return gebietsbaumStatusEntry;
  }

  private boolean reihenfolgeRelativePositionWeichtVonStimmzettelPositionAb(Gebiet gebiet, List<GruppeImGebiet> gruppenImGebiet) {
    List<GruppeImGebiet> gruppenImGebietSortiert = gruppenImGebiet.stream() //
        .filter(g -> g.getRelativePosition() != null) //
        .sorted(Comparator.comparing(GruppeImGebiet::getRelativePosition)) //
        .collect(toList());

    List<Wahlvorschlag> wahlvorschlaegeInWahl = wahlvorschlagRequestCache.getAlleWahlvorschlaege(gebiet.getWahl());

    EntityAufStimmzettelDaten entityAufStimmzettelDaten = new EntityAufStimmzettelDatenVorgeladenFactory(wahlParameterExtendedLoader, zulassungPrueferRequestScope.getZulassungPruefer(),
        stimmzettelFormatter, entityAufStimmzettelDatenStimmzettelPositionBerechnung, stimmenPoolExtendedDAOFactory, gruppeImGebietReihenfolgeVorsortierer, wahlvorschlaegeInWahl)
            .getEntityAufStimmzettelDaten();

    @SuppressWarnings("ConstantConditions")
    List<GruppeImGebiet> gigsNachStimmzettelPosition = gruppenImGebietSortiert.stream() //
        .flatMap(g -> g.getWahlvorschlagsByGruppeImGebiet().stream()) //
        .filter(wv -> wv.getStimmzettelPosition(gebiet, entityAufStimmzettelDaten).hasPosition()) //
        .sorted(Comparator.comparing(u -> u.getStimmzettelPosition(gebiet, entityAufStimmzettelDaten).getPosition())) //
        .map(Wahlvorschlag::getGruppeImGebiet) //
        .distinct() //
        .collect(toList());

    Integer letztePos = null;

    for (GruppeImGebiet gruppeImGebiet : gigsNachStimmzettelPosition) {
      int pos = gruppenImGebietSortiert.indexOf(gruppeImGebiet);

      if (pos > -1) {
        if (letztePos == null || letztePos < pos) {
          letztePos = pos;
        } else {
          return true;
        }
      }
    }

    return false;
  }
}
