
package de.ivu.elect.business.gruppeimgebiet.boundary;

import static java.util.Objects.nonNull;
import static java.util.function.Function.identity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.gebietsbaum.boundary.GebietDAO;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebiet;

@Stateless
public class GruppeImGebietReihenfolgeAufUntergebieteUebernehmer implements Serializable {

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

  private static final long serialVersionUID = 1L;

  @Inject
  private transient GruppeImGebietDAO gruppeImGebietDAO;

  @Inject
  private transient GebietDAO gebietDAO;

  public void uebernehmeReihenfolgeAufUntergeordneteGebiet(Gebiet gebietNotAttached,
      boolean includeUntergebieteMitWahlvorschlagOderMitEntsprechendemUntergebiet) {

    if (gebietNotAttached == null) {
      return;
    }

    Gebiet gebietQuelle = gebietDAO.attach(gebietNotAttached);

    LOG.info("Reihenfolge auf untergeordnete Gebiet übernehmen: gebiet=" + gebietQuelle);

    Map<Gebiet, List<GruppeImGebiet>> gigNachGebiet = GruppeImGebietEdit
        .bestimmeGruppeImGebiet(gebietQuelle, true, gebietDAO, gruppeImGebietDAO).stream()
        .collect(Collectors.groupingBy(GruppeImGebiet::getGebiet));

    Map<Gruppe, GruppeImGebiet> gigNachGruppeQuelle = gigNachGebiet.getOrDefault(gebietQuelle, Collections.emptyList()).stream()
        .collect(Collectors.toMap(GruppeImGebiet::getGruppe, identity()));

    if (!gigNachGebiet.isEmpty()) {
      for (Gebiet gebietZiel : new ArrayList<>(gigNachGebiet.keySet())) {
        if (gebietQuelle.equals(gebietZiel) || !includeUntergebieteMitWahlvorschlagOderMitEntsprechendemUntergebiet
            && gebietZiel.isWahlOderDirektwahlOderListenwahlgebietOderHatEntprechendesUntergebiet()) {
          continue;
        }
        List<GruppeImGebiet> gruppenImGebietZiel = gigNachGebiet.get(gebietZiel);
        positionenUebernehmen(gruppenImGebietZiel, gigNachGruppeQuelle);
      }
    }
  }

  private void positionenUebernehmen(List<GruppeImGebiet> gruppenImGebietZiel,
      Map<Gruppe, GruppeImGebiet> gigNachGruppeQuelle) {

    for (GruppeImGebiet gruppeImGebietZiel : gruppenImGebietZiel) {
      GruppeImGebiet gruppeImGebietQuelle = gigNachGruppeQuelle.get(gruppeImGebietZiel.getGruppe());
      if (nonNull(gruppeImGebietQuelle)) {
        gruppeImGebietZiel.setRelativePosition(gruppeImGebietQuelle.getRelativePosition());
        gruppeImGebietZiel.setEingereichtePosition(gruppeImGebietQuelle.getEingereichtePosition());
        gruppeImGebietZiel.setVorgegebenePosition(gruppeImGebietQuelle.getVorgegebenePosition());
      }
    }
  }
}
