
package de.ivu.elect.presentation.ergebnis.dokumente.gesamtergebnis.dhondt;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import de.ivu.document.generator.template.annotations.DocumentQueue;
import de.ivu.elect.business.ergebnis.control.ErgebnisDaten;
import de.ivu.elect.business.ergebnis.entity.DHondtQuotientListenInGruppe;
import de.ivu.elect.business.internet.control.GebietUndStimmabgabeart;
import de.ivu.elect.business.wahlvorschlag.control.WahlvorschlagByGebietComparator;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.dokumente.CoreElectContext;
import de.ivu.elect.presentation.gebietsbaum.GebietNummerFormatter;

public class DHondtQuotientenProPolitischeGruppeTabelleDocument extends AbstractDHondtQuotientTabelleDocument {

  private static final long serialVersionUID = 1L;

  @DocumentQueue(value = "ListenstimmenGesamt", elementClass = Long.class)
  public final LinkedList<Long> listenstimmenGesamt;

  public DHondtQuotientenProPolitischeGruppeTabelleDocument(CoreElectContext coreElectContext, ErgebnisDaten ergebnisDaten, GebietUndStimmabgabeart gebietUndStimmabgabeart,
      Collection<DHondtQuotientListenInGruppe> dHondtQuotientenListenInGruppe) {
    super( //
        erzeugeHeader(ergebnisDaten, coreElectContext.getGebietNummerFormatter(), dHondtQuotientenListenInGruppe), //
        erzeugeSitze(ergebnisDaten, dHondtQuotientenListenInGruppe), //
        erzeugeZeilen(ergebnisDaten, dHondtQuotientenListenInGruppe) //
    );

    this.listenstimmenGesamt = new LinkedList<>();

    for (Liste liste : collectListenSorted(ergebnisDaten, dHondtQuotientenListenInGruppe)) {
      Long anzahlListenstimmenGesamt = ergebnisDaten.getZweitstimmenAktuell(liste.getGruppe(), gebietUndStimmabgabeart);

      if (anzahlListenstimmenGesamt == null) {
        anzahlListenstimmenGesamt = 0L;
      }

      this.listenstimmenGesamt.add(anzahlListenstimmenGesamt);
    }
  }

  private static List<String> erzeugeHeader(ErgebnisDaten ergebnisDaten, GebietNummerFormatter gebietNummerFormatter, Collection<DHondtQuotientListenInGruppe> dHondtQuotientenListenInGruppe) {
    List<String> result = new ArrayList<>();

    for (Liste liste : collectListenSorted(ergebnisDaten, dHondtQuotientenListenInGruppe)) {
      result.add(gebietNummerFormatter.getName(liste.getGebiet()));
    }

    return result;
  }

  private static List<Long> erzeugeSitze(ErgebnisDaten ergebnisDaten, Collection<DHondtQuotientListenInGruppe> dHondtQuotientenListenInGruppe) {
    List<Long> result = new ArrayList<>(dHondtQuotientenListenInGruppe.size());

    for (Liste liste : collectListenSorted(ergebnisDaten, dHondtQuotientenListenInGruppe)) {
      long anzahlSitze = 0L;

      for (DHondtQuotientListenInGruppe dHondtQuotientListenInGruppe : dHondtQuotientenListenInGruppe) {
        if (liste.equals(dHondtQuotientListenInGruppe.getListe()) && Boolean.TRUE.equals(dHondtQuotientListenInGruppe.getSitzgewinn())) {
          anzahlSitze++;
        }
      }

      result.add(anzahlSitze);
    }

    return result;
  }

  private static List<DHondtTableRow> erzeugeZeilen(ErgebnisDaten ergebnisDaten, Collection<DHondtQuotientListenInGruppe> dHondtQuotientenListenInGruppe) {
    return erzeugeZeilen(dHondtQuotientenListenInGruppe, collectListenSorted(ergebnisDaten, dHondtQuotientenListenInGruppe),
        (dHondtQuotientListenInGruppe, liste) -> liste.equals(dHondtQuotientListenInGruppe.getListe()));
  }

  private static List<Liste> collectListenSorted(ErgebnisDaten ergebnisDaten, Collection<DHondtQuotientListenInGruppe> dHondtQuotientenListenInGruppe) {
    Set<Liste> listen = new HashSet<>();

    for (DHondtQuotientListenInGruppe dHondtQuotientListenInGruppe : dHondtQuotientenListenInGruppe) {
      listen.add(dHondtQuotientListenInGruppe.getListe());
    }

    List<Liste> result = new ArrayList<>(listen);
    Collections.sort(result, new WahlvorschlagByGebietComparator());

    return result;
  }

}
