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

import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.kandidatur.entity.Kandidatur;
import de.ivu.elect.business.sitzberechnung.control.Sitzberechnungsalgorithmus;
import de.ivu.elect.business.sitzberechnung.entity.SitzberechnungsalgorithmusKonfiguration;
import de.ivu.elect.business.sitzberechnung.entity.Sitzberechnungseingabe;
import de.ivu.elect.business.sitzberechnung.entity.Sitzberechnungsergebnis;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.business.wahlvorschlag.entity.Wahlvorschlag;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.presentation.kandidatur.table.KandidaturGewaehltKeinSitzberechnungsalgorithmusColumnBuilder;
import de.ivu.elect.presentation.kandidatur.table.KandidaturGewaehltSitzberechnungsalgorithmusColumnBuilder;
import de.ivu.elect.sitzberechnung.Waehlbarkeit;
import de.ivu.elect.was.sitzberechnung.entity.ElectSitzberechnungseingabe;
import de.ivu.elect.was.sitzberechnung.entity.KonfliktMapper;
import de.ivu.elect.was.sitzberechnung.entity.SitzberechnungMappingContext;

import javax.annotation.Nullable;
import javax.inject.Inject;
import java.util.Collection;
import java.util.function.Function;

public abstract class AbstractBasisSitzberechnungsalgorithmus<K extends SitzberechnungsalgorithmusKonfiguration> implements Sitzberechnungsalgorithmus<K> {

  @Inject
  transient SitzberechnungeingabeMapper sitzberechnungeingabeMapper;

  @Inject
  transient SitzberechnungsergebnisMapper sitzberechnungsergebnisMapper;

  @Override
  public Sitzberechnungsergebnis berechneSitzverteilung(Sitzberechnungseingabe<K> sitzberechnungseingabe) {
    SitzberechnungMappingContext sitzberechnungMappingContext = getSitzberechnungMappingContext();
    sitzberechnungMappingContext.setWahl(sitzberechnungseingabe.getErgebnis().getWahl());
    return mappeErgebnis(berechneErgebnis(sitzberechnungseingabe, sitzberechnungMappingContext), sitzberechnungMappingContext);
  }

  protected abstract de.ivu.elect.sitzberechnung.Sitzberechnungsergebnis berechneErgebnis(Sitzberechnungseingabe<K> sitzberechnungseingabe, SitzberechnungMappingContext sitzberechnungMappingContext);

  protected Sitzberechnungsergebnis mappeErgebnis(de.ivu.elect.sitzberechnung.Sitzberechnungsergebnis sitzberechnungsergebnis, SitzberechnungMappingContext mappingContext) {
    return sitzberechnungsergebnisMapper.mappe(sitzberechnungsergebnis, getKonfliktMapper(), mappingContext);
  }

  protected ElectSitzberechnungseingabe mappeEingabe(Sitzberechnungseingabe<K> sitzberechnungseingabe, Wahldurchfuehrungsgebiet wahlgebiet, SitzberechnungMappingContext sitzberechnungMappingContext) {
    return sitzberechnungeingabeMapper.mappe(sitzberechnungseingabe, wahlgebiet, getKonfliktMapper(), this::getWaehlbarkeit, sitzberechnungMappingContext);
  }

  protected abstract SitzberechnungMappingContext getSitzberechnungMappingContext();

  protected abstract KonfliktMapper getKonfliktMapper();

  protected abstract Waehlbarkeit getWaehlbarkeit(Kandidatur kandidatur);

  @Override
  public KandidaturGewaehltSitzberechnungsalgorithmusColumnBuilder getKandidaturGewaehltColumnBuilder(Messages messages) {
    return new KandidaturGewaehltKeinSitzberechnungsalgorithmusColumnBuilder(messages);
  }

  @Override
  public boolean isBerechnetErgebnis() {
    return true;
  }

  @Override
  public boolean isBerechnetErgebnisFallsWaehlerBenannteWahlvorschlaegeSonstigeErfasst() {
    return isBerechnetErgebnis(); // ????
  }


  @Override
  public boolean isErstelltDHondtQuotientPolitischeGruppe() {
    return false;
  }

  @Override
  public boolean isErstelltDHondtQuotientListenInGruppe() {
    return false;
  }

  @Override
  public boolean isErstelltDHondtQuotientListenInListenverbindung() {
    return false;
  }

  @Override
  public boolean isErstelltDHondtQuotientListenImGebiet() {
    return false;
  }

  @Override
  public boolean isWaehlerBenannteWahlvorschlaegeErfassbar(Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet, Collection<? extends Wahlvorschlag> wahlvorschlaege) {
    return false; // ?
  }

  @Nullable
  @Override
  public Wahldurchfuehrungsgebiet getWaehlerBenannteListeListengebietFuerErfassungsgebiet(Wahldurchfuehrungsgebiet erfassungsgebiet, Function<Wahldurchfuehrungsgebiet, Collection<Liste>> listenByGebietFunction) {
    return null;
  }


}
