package de.ivu.elect.was.sitzberechnung.control;

import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.gruppe.entity.PolitischeGruppe;
import de.ivu.elect.business.wahlvorschlag.entity.NlListe;
import de.ivu.elect.sitzberechnung.Liste;
import de.ivu.elect.sitzberechnung.osv.exchange.OSVLegacySitzberechnungWahlart;
import de.ivu.elect.sitzberechnung.osv.exchange.OSVLegacySitzberechnungseingabe;
import de.ivu.elect.was.sitzberechnung.entity.AbstractElectSitzberechnungEntity;
import de.ivu.elect.was.sitzberechnung.entity.KonfliktMapper;
import de.ivu.elect.was.sitzberechnung.entity.SitzberechnungListe;
import de.ivu.elect.was.sitzberechnung.entity.SitzberechnungStel;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class OsvLegacySitzberechnungsalgorithmusMapper {

  @Inject
  private transient OsvLegacyKonfliktMapper osvLegacyKonflikteMapper;

  public OSVLegacySitzberechnungseingabe mappeOsvEingabe(OSVLegacySitzberechnungWahlart osvLegacySitzberechnungWahlart,
                                                         Set<Liste> gemappteListen, List<Wahldurchfuehrungsgebiet> gebiete,
                                                         int preferencialBarrierNumerator, int preferencialBarrierDenominator) {
    return new ElectOSVLegacySitzberechnungseingabe(osvLegacySitzberechnungWahlart, computeStelsFuerListenMap(gemappteListen), preferencialBarrierNumerator, preferencialBarrierDenominator, createGebietsnummerMap(gebiete));
  }

  private Map<String, String> createGebietsnummerMap(List<Wahldurchfuehrungsgebiet> gebiete) {
    return gebiete.stream().collect(Collectors.toMap(g -> g.getPk().toString(), Gebiet::getNummer));
  }

  Map<Liste, SitzberechnungStel> computeStelsFuerListenMap(Set<Liste> gemappteListen) {
    Map<Liste, SitzberechnungStel> stelsFuerListen = new HashMap<>();

    Map<PolitischeGruppe, Map<Integer, List<SitzberechnungListe>>> listenNachPolitischerGruppeUndStelNummer = new HashMap<>();

    for (Liste liste : gemappteListen) {
      SitzberechnungListe sitzberechnungListe = (SitzberechnungListe) liste;
      NlListe.getStelNummerWas(sitzberechnungListe.getEntity()).ifPresent(s -> listenNachPolitischerGruppeUndStelNummer
              .computeIfAbsent(sitzberechnungListe.getEntity().getGruppe(), x -> new HashMap<>())
              .computeIfAbsent(s, x -> new ArrayList<>()).add(sitzberechnungListe));
    }

    for (Map.Entry<PolitischeGruppe, Map<Integer, List<SitzberechnungListe>>> e : listenNachPolitischerGruppeUndStelNummer.entrySet()) {
      PolitischeGruppe politischeGruppe = e.getKey();
      for (Map.Entry<Integer, List<SitzberechnungListe>> stelsDerGruppe : e.getValue().entrySet()) {
        Integer stelNummer = stelsDerGruppe.getKey();
        List<SitzberechnungListe> listenDesStels = stelsDerGruppe.getValue();
        SitzberechnungStel sitzberechnungStel = new SitzberechnungStel(politischeGruppe, stelNummer,
                listenDesStels.stream().map(AbstractElectSitzberechnungEntity::getEntity).collect(Collectors.toList()));
        for (SitzberechnungListe listeDesStels : listenDesStels) {
          stelsFuerListen.put(listeDesStels, sitzberechnungStel);
        }
      }
    }
    return stelsFuerListen;
  }

  protected KonfliktMapper getKonfliktMapper() {
    return osvLegacyKonflikteMapper;
  }

}
