
package de.ivu.elect.business.hochrechnung.entity;

import java.util.Collection;
import java.util.function.Function;

import de.ivu.elect.business.ergebnis.entity.Stimmenart;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.stimmzettel.boundary.AnzahlStimmenProWaehlerBestimmer;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahlvorschlag.entity.Direktkandidat;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;

public class EinfacheWahlAnzahlStimmenProWaehlerNachStimmenartBestimmer implements AnzahlStimmenProWaehlerNachStimmenartBestimmer {
  public static final double ANTEIL_VOM_WAEHLER_BENUTZTE_STIMMEN_DURCHSCHNITTLICH_WENN_ANZAHL_STIMMEN_PRO_GLEICH_EINS = 1; // Schätzung, kann durch eine Funktion ersetzt werden
  public static final double ANTEIL_VOM_WAEHLER_BENUTZTE_STIMMEN_DURCHSCHNITTLICH_WENN_ANZAHL_STIMMEN_PRO_WAEHLER_UNTER_ZEHN = 0.9; // Schätzung, kann durch eine Funktion ersetzt werden
  public static final double ANTEIL_VOM_WAEHLER_BENUTZTE_STIMMEN_DURCHSCHNITTLICH_WENN_ANZAHL_STIMMEN_PRO_WAEHLER_ZWISCHEN_ZEHN_UND_ZWANZIG = 0.8; // Schätzung, kann durch eine Funktion ersetzt werden
  public static final double ANTEIL_VOM_WAEHLER_BENUTZTE_STIMMEN_DURCHSCHNITTLICH_WENN_ANZAHL_STIMMEN_PRO_WAEHLER_UEBER_ZWANZIG = 0.70; // Schätzung, kann durch eine Funktion ersetzt werden

  private final AnzahlStimmenProWaehlerNachStimmenartBestimmer anzahlStimmenProWaehlerNachStimmenartBestimmer;

  public EinfacheWahlAnzahlStimmenProWaehlerNachStimmenartBestimmer(AnzahlStimmenProWaehlerBestimmer anzahlStimmenProWaehlerBestimmer, Function<Gebiet, Collection<Direktkandidat>> wahlvorschlaegeInDirektwahlgebietFct, Function<Gebiet, Collection<Liste>> wahlvorschlaegeInListenwahlgebietFct) {
    anzahlStimmenProWaehlerNachStimmenartBestimmer = new AnzahlStimmenProWaehlerNachStimmenartBestimmer() {

      @Override
      public Long getAnzahlStimmenProWaehlerProDirektkandidaturMaximalPerGebiet(Gebiet gebiet) {
        return anzahlStimmenProWaehlerBestimmer.getAnzahlStimmenProWaehlerProDirektkandidaturMaximal(gebiet, wahlvorschlaegeInDirektwahlgebietFct);
      }

      @Override
      public Long getAnzahlStimmenProWaehlerProListenkandidaturMaximalPerGebiet(Gebiet gebiet) {
        return anzahlStimmenProWaehlerBestimmer.getAnzahlStimmenProWaehlerProListenkandidaturMaximal(gebiet, wahlvorschlaegeInListenwahlgebietFct);
      }

      @Override
      public Long getAnzahlStimmenProWaehlerProStimmenartMaximal(Stimmenart stimmenart, Gebiet gebiet) {
        // Nach de.ivu.elect.presentation.stimmeingabe.AbstractStimmeingabeErfassenView.getErfassungshinweise
        Long anzahlStimmenProWaehlerMaximal = anzahlStimmenProWaehlerBestimmer.getAnzahlStimmenProWaehlerMaximal(gebiet);
        return isWahlMitStimmenart(gebiet, stimmenart)? anzahlStimmenProWaehlerMaximal : null;
      }

      private boolean isWahlMitStimmenart(Gebiet gebiet, Stimmenart stimmenart) {
        if (gebiet == null) {
          return false;
        }
        Wahl wahl = gebiet.getWahl();
        if (wahl == null) {
          return false;
        }
        if (stimmenart.equals(Stimmenart.DIREKTSTIMME)) {
          return wahl.isWahlMitDirektkandidatengebieten();
        }
        if (stimmenart.equals(Stimmenart.LISTENSTIMME)) {
          return wahl.isWahlMitListengebieten();
        }
        if (stimmenart.equals(Stimmenart.REFERENDUM_STIMME)) {
          return wahl.isWahlMitReferendengebieten();
        }
        return false;
      }

      @Override
      public double getAnteilVomWaehlerBenutzteStimmenDurchschnittlich(Stimmenart stimmenart, Gebiet gebiet) {
        Long anzahlStimmenProWaehlerProStimmenartMaximal = anzahlStimmenProWaehlerNachStimmenartBestimmer.getAnzahlStimmenProWaehlerProStimmenartMaximal(stimmenart, gebiet);
        if (anzahlStimmenProWaehlerProStimmenartMaximal == null || anzahlStimmenProWaehlerProStimmenartMaximal < 0) {
          return 0;
        } else if (anzahlStimmenProWaehlerProStimmenartMaximal == 1) {
          return ANTEIL_VOM_WAEHLER_BENUTZTE_STIMMEN_DURCHSCHNITTLICH_WENN_ANZAHL_STIMMEN_PRO_GLEICH_EINS;
        } else if (anzahlStimmenProWaehlerProStimmenartMaximal <= 10) {
          return ANTEIL_VOM_WAEHLER_BENUTZTE_STIMMEN_DURCHSCHNITTLICH_WENN_ANZAHL_STIMMEN_PRO_WAEHLER_UNTER_ZEHN;
        } else if (anzahlStimmenProWaehlerProStimmenartMaximal <= 20) {
          return ANTEIL_VOM_WAEHLER_BENUTZTE_STIMMEN_DURCHSCHNITTLICH_WENN_ANZAHL_STIMMEN_PRO_WAEHLER_ZWISCHEN_ZEHN_UND_ZWANZIG;
        } else {
          return ANTEIL_VOM_WAEHLER_BENUTZTE_STIMMEN_DURCHSCHNITTLICH_WENN_ANZAHL_STIMMEN_PRO_WAEHLER_UEBER_ZWANZIG;
        }
      }
    };
  }

  @Override
  public Long getAnzahlStimmenProWaehlerProDirektkandidaturMaximalPerGebiet(Gebiet gebiet) {
    return anzahlStimmenProWaehlerNachStimmenartBestimmer.getAnzahlStimmenProWaehlerProDirektkandidaturMaximalPerGebiet(gebiet);
  }

  @Override
  public Long getAnzahlStimmenProWaehlerProListenkandidaturMaximalPerGebiet(Gebiet gebiet) {
    return anzahlStimmenProWaehlerNachStimmenartBestimmer.getAnzahlStimmenProWaehlerProListenkandidaturMaximalPerGebiet(gebiet);
  }

  @Override
  public double getAnteilVomWaehlerBenutzteStimmenDurchschnittlich(Stimmenart stimmenart, Gebiet gebiet) {
    return anzahlStimmenProWaehlerNachStimmenartBestimmer.getAnteilVomWaehlerBenutzteStimmenDurchschnittlich(stimmenart, gebiet);
  }

  @Override
  public Long getAnzahlStimmenProWaehlerProStimmenartMaximal(Stimmenart stimmenart, Gebiet gebiet) {
    return anzahlStimmenProWaehlerNachStimmenartBestimmer.getAnzahlStimmenProWaehlerProStimmenartMaximal(stimmenart, gebiet);
  }
}
