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

import java.math.BigDecimal;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;

import de.ivu.elect.was.sitzberechnung.entity.AbstractElectSitzberechnungKandidatur;
import de.ivu.elect.was.sitzberechnung.entity.ElectSitzberechnungGebiet;
import de.ivu.elect.was.sitzberechnung.entity.ElectSitzberechnungListe;

public class ElectSitzberechnungseingabe implements de.ivu.elect.sitzberechnung.Sitzberechnungseingabe {

  private final de.ivu.elect.sitzberechnung.SitzberechnungLokalisierung sitzberechnungLokalisierung;

  private final de.ivu.elect.sitzberechnung.Gebiet wahlgebiet;

  private final Optional<BigDecimal> quorumProzenthuerdeDezimal;

  private final Map<de.ivu.elect.sitzberechnung.Gebiet, Long> anzahlSitzePerGebiet;

  private final Collection<de.ivu.elect.sitzberechnung.Gebiet> gebiete;

  private final Collection<de.ivu.elect.sitzberechnung.Liste> listen;

  private final Collection<de.ivu.elect.sitzberechnung.Kandidatur> direktkandidaturen;

  private final Collection<de.ivu.elect.sitzberechnung.Kandidatur> listenkandidaturen;

  private final Map<de.ivu.elect.sitzberechnung.Liste, Long> anzahlStimmenPerListe;

  private final Map<de.ivu.elect.sitzberechnung.Kandidatur, Long> anzahlStimmenPerKandidatur;

  private final Map<de.ivu.elect.sitzberechnung.Minderheitengruppe, Long> anzahlSitzePerMinderheitengruppe;

  private final Collection<de.ivu.elect.sitzberechnung.konflikt.ErgebnisKonflikt> konflikte;

  public ElectSitzberechnungseingabe(ElectSitzberechnungLokalisierung sitzberechnungLokalisierung, ElectSitzberechnungGebiet wahlgebiet, Optional<BigDecimal> quorumProzenthuerdeDezimal,
      Map<ElectSitzberechnungGebiet, Long> anzahlSitzePerGebiet, Collection<ElectSitzberechnungGebiet> gebiete, Map<ElectSitzberechnungListe, Long> anzahlStimmenPerListe,
      Map<AbstractElectSitzberechnungKandidatur< ? >, Long> anzahlStimmenPerKandidatur, Map<de.ivu.elect.sitzberechnung.Minderheitengruppe, Long> anzahlSitzePerMinderheitengruppe,
      Collection<de.ivu.elect.sitzberechnung.konflikt.ErgebnisKonflikt> konflikte) {
    super();

    this.sitzberechnungLokalisierung = sitzberechnungLokalisierung;

    this.wahlgebiet = wahlgebiet;

    this.quorumProzenthuerdeDezimal = quorumProzenthuerdeDezimal;

    this.anzahlSitzePerGebiet = new HashMap<>(anzahlSitzePerGebiet);

    this.gebiete = new HashSet<>(gebiete);

    this.anzahlStimmenPerListe = new HashMap<>(anzahlStimmenPerListe);
    this.anzahlStimmenPerKandidatur = new HashMap<>(anzahlStimmenPerKandidatur);

    this.listen = new HashSet<>(anzahlStimmenPerListe.keySet());

    this.direktkandidaturen = new HashSet<>();
    this.listenkandidaturen = new HashSet<>();

    for (AbstractElectSitzberechnungKandidatur< ? > kandidatur : anzahlStimmenPerKandidatur.keySet()) {
      if (kandidatur.isDirektkandidatur()) {
        this.direktkandidaturen.add(kandidatur);
      } else {
        this.listenkandidaturen.add(kandidatur);
      }
    }

    this.anzahlSitzePerMinderheitengruppe = new HashMap<>(anzahlSitzePerMinderheitengruppe);

    this.konflikte = konflikte;
  }

  @Override
  public de.ivu.elect.sitzberechnung.Gebiet getWahlgebiet() {
    return wahlgebiet;
  }

  @Override
  public long getAnzahlSitze(de.ivu.elect.sitzberechnung.Gebiet gebiet) {
    return fixNonPositiveToZero(anzahlSitzePerGebiet.get(gebiet));
  }

  @Override
  public Optional<BigDecimal> getQuorumProzenthuerdeDezimal() {
    return quorumProzenthuerdeDezimal;
  }

  @Override
  public Collection<de.ivu.elect.sitzberechnung.Gebiet> getGebiete() {
    return gebiete;
  }

  @Override
  public Collection<de.ivu.elect.sitzberechnung.Liste> getListen() {
    return listen;
  }

  @Override
  public long getAnzahlStimmen(de.ivu.elect.sitzberechnung.Liste liste) {
    return fixNonPositiveToZero(anzahlStimmenPerListe.get(liste));
  }

  @Override
  public Collection<de.ivu.elect.sitzberechnung.Kandidatur> getDirektkandidaturen() {
    return direktkandidaturen;
  }

  @Override
  public Collection<de.ivu.elect.sitzberechnung.Kandidatur> getListenkandidaturen() {
    return listenkandidaturen;
  }

  @Override
  public long getAnzahlStimmen(de.ivu.elect.sitzberechnung.Kandidatur kandidatur) {
    return fixNonPositiveToZero(anzahlStimmenPerKandidatur.get(kandidatur));
  }

  @Override
  public Collection<de.ivu.elect.sitzberechnung.Minderheitengruppe> getMinderheitengruppen() {
    return anzahlSitzePerMinderheitengruppe.keySet();
  }

  @Override
  public long getAnzahlSitze(de.ivu.elect.sitzberechnung.Minderheitengruppe minderheitengruppe) {
    return fixNonPositiveToZero(anzahlSitzePerMinderheitengruppe.get(minderheitengruppe));
  }

  @Override
  public Collection<de.ivu.elect.sitzberechnung.konflikt.ErgebnisKonflikt> getKonflikte() {
    return konflikte;
  }

  @Override
  public de.ivu.elect.sitzberechnung.SitzberechnungLokalisierung getSitzberechnungLokalisierung() {
    return sitzberechnungLokalisierung;
  }

  private static long fixNonPositiveToZero(Long result) {
    if (result == null || result < 1L) {
      return 0L;
    }

    return result;
  }
}
