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

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebiet;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebietTK;
import de.ivu.elect.business.wahlvorschlag.boundary.AbstractWahlvorschlagDAO;
import de.ivu.elect.business.wahlvorschlag.entity.Direktkandidat;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.business.wahlvorschlag.entity.ReferendumOption;
import de.ivu.elect.business.wahlvorschlag.entity.Wahlvorschlag;

public class GruppeImGebietWahlvorschlaegeInHierarchiePreloader implements Serializable {

  private static final long serialVersionUID = 1L;

  public GruppeImGebietWahlvorschlaegeInHierarchiePreloader() {
    super();
  }

  // ELECT-1886 Preloading von Daten der Gebietshierarchie für Performance-Optimierung
  public void preloadGruppeImGebietWahlvorschlaegeInHierarchie(Collection<GruppeImGebiet> gruppenImGebiet, Gebiet gebiet,
      AbstractWahlvorschlagDAO wahlvorschlagDAO) {

    for (GruppeImGebiet gruppeImGebiet : gruppenImGebiet) {
      gruppeImGebiet.setListenInUebergeordneterGebietshierarchie(new ArrayList<>(1));
      gruppeImGebiet.setDirektkandidatenInUebergeordneterGebietshierarchie(new ArrayList<>(1));
      gruppeImGebiet.setReferendumOptionenInUebergeordneterGebietshierarchie(new ArrayList<>());
    }

    Collection<Gebiet> gebieteInHierarchie = gebiet.getInGebietshierarchieUebergeordneteGebiete();
    Map<GruppeImGebietTK, GruppeImGebiet> gruppeImGebietPerSchluessel = GruppeImGebiet
        .mappeNachGruppeGebietSchluessel(gruppenImGebiet);

    Set<Gebiet> gebiete = new HashSet<>();
    Gebiet aktuellesGebiet = gebiet;
    while (aktuellesGebiet != null) {
      gebiete.add(aktuellesGebiet);
      aktuellesGebiet = aktuellesGebiet.getUebergeordnetesGebiet();
    }
    if (!gebiete.isEmpty()) {
      List<Wahlvorschlag> wahlvorschlaege = wahlvorschlagDAO.findByGebiete(gebiete); // Interessant sind nur die Wahlvorschläge aus den übergeordneten Gebieten, nicht alle Wahlvorschläge der Wahl...
      for (Wahlvorschlag wahlvorschlag : wahlvorschlaege) {
        if (gebiet.equals(wahlvorschlag.getGebiet()) || gebieteInHierarchie.contains(wahlvorschlag.getGebiet())) {
          GruppeImGebiet gruppeImGebiet = gruppeImGebietPerSchluessel.get(new GruppeImGebietTK(gebiet.getGebietTK(), wahlvorschlag.getGruppe().getGruppeTK()));

          if (gruppeImGebiet != null) {
            if (wahlvorschlag.isListe()) {
              gruppeImGebiet.getListenInUebergeordneterGebietshierarchie().add(wahlvorschlag.castTo(Liste.class).getEntity());
            }

            if (wahlvorschlag.isDirektkandidat()) {
              gruppeImGebiet.getDirektkandidatenInUebergeordneterGebietshierarchie()
                  .add(wahlvorschlag.castTo(Direktkandidat.class).getEntity());
            }

            if (wahlvorschlag.isReferendumOption()) {
              gruppeImGebiet.getReferendumOptionenInUebergeordneterGebietshierarchie()
                  .add(wahlvorschlag.castTo(ReferendumOption.class).getEntity());
            }
          } else {
            throw new IllegalStateException("In Gebiet [gebiet=" + gebiet + "] konnte für Wahlvorschlag [wahlvorschlag=" + wahlvorschlag
                + "] keine Gruppe [gruppe=" + wahlvorschlag.getGruppe() + "] gefunden werden!");
          }
        }
      }
    }
  }

}
