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

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.inject.Inject;

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.ElectSitzberechnungListe;
import de.ivu.elect.was.sitzberechnung.entity.SitzberechnungStel;

public class OsvLegacySitzberechnungsalgorithmusMapper {

  @Inject
  private transient OsvLegacyKonfliktMapper osvLegacyKonflikteMapper;

  public OSVLegacySitzberechnungseingabe mappeOsvEingabe(OSVLegacySitzberechnungWahlart osvLegacySitzberechnungWahlart,
                                                         Collection<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(Collection<Liste> gemappteListen) {
    Map<Liste, SitzberechnungStel> stelsFuerListen = new HashMap<>();

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

    for (Liste liste : gemappteListen) {
      ElectSitzberechnungListe sitzberechnungListe = (ElectSitzberechnungListe) 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<ElectSitzberechnungListe>>> e : listenNachPolitischerGruppeUndStelNummer.entrySet()) {
      PolitischeGruppe politischeGruppe = e.getKey();
      for (Map.Entry<Integer, List<ElectSitzberechnungListe>> stelsDerGruppe : e.getValue().entrySet()) {
        Integer stelNummer = stelsDerGruppe.getKey();
        List<ElectSitzberechnungListe> listenDesStels = stelsDerGruppe.getValue();
        SitzberechnungStel sitzberechnungStel = new SitzberechnungStel(politischeGruppe, stelNummer,
                listenDesStels.stream().map(AbstractElectSitzberechnungEntity::getEntity).collect(Collectors.toList()));
        for (ElectSitzberechnungListe listeDesStels : listenDesStels) {
          stelsFuerListen.put(listeDesStels, sitzberechnungStel);
        }
      }
    }
    return stelsFuerListen;
  }

  protected ElectErgebnisKonfliktMapper getKonfliktMapper() {
    return osvLegacyKonflikteMapper;
  }

}
