
package de.ivu.elect.dokumente.ergebnistabelle.kandidaten;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import de.ivu.elect.business.ergebnis.control.ErgebnisDatenListenkandidaturen;
import de.ivu.elect.business.ergebnis.entity.Stimmabgabeart;
import de.ivu.elect.business.ergebnis.entity.Stimmen;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.gruppe.entity.PolitischeGruppe;
import de.ivu.elect.business.internet.control.PolitischeGruppeUndGebietUndStimmabgabeart;
import de.ivu.elect.business.kandidatur.control.ListenkandidaturByRelativePositionComparator;
import de.ivu.elect.business.kandidatur.entity.Listenkandidatur;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.core.exchange.stimmen.csv.AbstractStimmenMapper;

public class ListenkandidaturenErgebnistabelleCsvDTOFactory extends AbstractStimmenMapper {

  public ListenkandidaturenErgebnistabelleCsvDTOFactory() {
    super();
  }

  public Class< ? extends ListenkandidaturenErgebnistabelleCsvDTO> getCsvDTOClass(Wahl wahl) {
    return DefaultListenkandidaturenErgebnistabelleCsvDTO.class;
  }

  public ListenkandidaturenErgebnistabelleCsvDTO createCsvDTO(Wahl wahl, ListenkandidaturenErgebnistabelleZeilenSchluessel schluessel) {
    return new DefaultListenkandidaturenErgebnistabelleCsvDTO(schluessel);
  }

  public ListenkandidaturenErgebnistabelleCsvDTO createListenkandidaturenErgebnistabelleCsvDTO(Wahl wahl, ErgebnisDatenListenkandidaturen ergebnisDatenListenkandidaturen,
      ListenkandidaturenErgebnistabelleZeilenSchluessel schluessel, Map<Gebiet, Map<Gruppe, List<Stimmen>>> systemgruppenStimmenByGebietUndGruppe) {
    PolitischeGruppeUndGebietUndStimmabgabeart politischeGruppeUndGebietUndStimmabgabeart = schluessel.getPolitischeGruppeUndGebietUndStimmabgabeart();

    PolitischeGruppe politischeGruppe = politischeGruppeUndGebietUndStimmabgabeart.getPolitischeGruppe();
    Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = politischeGruppeUndGebietUndStimmabgabeart.getWahldurchfuehrungsgebiet();
    Stimmabgabeart stimmabgabeart = politischeGruppeUndGebietUndStimmabgabeart.getStimmabgabeart();

    ListenkandidaturenErgebnistabelleCsvDTO dto = createCsvDTO(wahl, schluessel);

    addWahlberechtigteToCsvDTO(dto, wahldurchfuehrungsgebiet, stimmabgabeart, systemgruppenStimmenByGebietUndGruppe);
    addWaehlerToCsvDTO(dto, wahldurchfuehrungsgebiet, stimmabgabeart, systemgruppenStimmenByGebietUndGruppe);

    Map<Listenkandidatur, Long> stimmenFuerListenkandidaturen = ergebnisDatenListenkandidaturen.collectStimmenPerListenkandidatur(politischeGruppeUndGebietUndStimmabgabeart);

    dto.setAnzahlStimmenNurListe(ergebnisDatenListenkandidaturen.getStimmenFuerListeAbzueglichStimmenFuerAlleListenkandidaturen(politischeGruppeUndGebietUndStimmabgabeart));
    dto.setAnzahlStimmenNurListenkandidaturen(ergebnisDatenListenkandidaturen.getStimmenFuerListenkandidaturen(politischeGruppeUndGebietUndStimmabgabeart));

    for (Listenkandidatur listenkandidatur : getRelevanteListenkandidaturenSortiert(politischeGruppe, wahldurchfuehrungsgebiet, ergebnisDatenListenkandidaturen)) {
      dto.addListenkandidaturStimmen(stimmenFuerListenkandidaturen.get(listenkandidatur));
    }

    return dto;
  }

  public List<Listenkandidatur> getRelevanteListenkandidaturenSortiert(Gruppe gruppe, Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet,
      ErgebnisDatenListenkandidaturen ergebnisDatenListenkandidaturen) {
    List<Listenkandidatur> result = new ArrayList<>(ergebnisDatenListenkandidaturen.getListenkandidaturenAufStimmzettelFuerGruppeAufGebiet(gruppe, wahldurchfuehrungsgebiet));
    Collections.sort(result, new ListenkandidaturByRelativePositionComparator());

    return result;
  }
}
