
package de.ivu.elect.business.ergebnis.control;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.Locale;
import java.util.function.ToLongFunction;

import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.wahl.entity.Wahl;

public class ErgebnisDatenQuorum<G extends Gebiet> {

  private final Wahl wahl;

  private final ToLongFunction<G> grundwertFct;

  public ErgebnisDatenQuorum(Wahl wahl, ToLongFunction<G> grundwertFct) {
    super();

    this.wahl = wahl;

    this.grundwertFct = grundwertFct;
  }

  private Wahl getWahl() {
    return wahl;
  }

  public boolean isProzentsatzVorhanden() {
    return getProzentsatzDezimal().compareTo(BigDecimal.ZERO) > 0;
  }

  public BigDecimal getProzentsatz() {
    return getProzentsatz(getWahl());
  }

  public BigDecimal getProzentsatzDezimal() {
    return getProzentsatzDezimal(getWahl());
  }

  public String getProzentsatzFormatted(Locale locale) {
    return NumberFormat.getPercentInstance(locale).format(getProzentsatzDezimal());
  }

  public boolean isGrundwertVorhanden(G gebiet) {
    return getGrundwert(gebiet) > 0;
  }

  public long getGrundwert(G gebiet) {
    return grundwertFct.applyAsLong(gebiet);
  }

  public static BigDecimal getProzentsatz(Wahl wahl) {
    if (wahl != null) {
      BigDecimal result = wahl.getQuorumProzenthuerde();

      if (result != null) {
        return result;
      }
    }

    return BigDecimal.ZERO;
  }

  public static BigDecimal getProzentsatzDezimal(Wahl wahl) {
    if (wahl != null) {
      BigDecimal result = wahl.getQuorumProzenthuerdeDezimal();

      if (result != null) {
        return result;
      }
    }

    return BigDecimal.ZERO;
  }

  /**
   * @param gebiet
   * @return Anzahl Quorum erreicht um eins erhöht
   *
   * @deprecated Anzahl Quorum erreicht sollte in den meisten Fällen die richtige Wahl sein!
   * @see ErgebnisDatenQuorum#getAnzahlQuorumErreicht
   */
  @Deprecated
  public long getAnzahlQuorumUeberschritten(G gebiet) {
    return calculateAnzahlQuorumUeberschritten(getWahl(), getGrundwert(gebiet));
  }

  /**
   * @param wahl
   * @param grundwert
   * @return Anzahl Quorum erreicht um eins erhöht
   *
   * @deprecated Anzahl Quorum erreicht sollte in den meisten Fällen die richtige Wahl sein!
   * @see ErgebnisDatenQuorum#getAnzahlQuorumErreicht
   */
  @Deprecated
  public static long calculateAnzahlQuorumUeberschritten(Wahl wahl, Long grundwert) {
    if (wahl == null) {
      return 0L;
    }

    return calculateAnzahlQuorumUeberschritten(wahl.getQuorumProzenthuerde(), grundwert);
  }

  /**
   * @param prozentsatz
   * @param grundwert
   * @return Anzahl Quorum erreicht um eins erhöht
   *
   * @deprecated Anzahl Quorum erreicht sollte in den meisten Fällen die richtige Wahl sein!
   * @see ErgebnisDatenQuorum#getAnzahlQuorumErreicht
   */
  @Deprecated
  public static long calculateAnzahlQuorumUeberschritten(BigDecimal prozentsatz, Long grundwert) {
    long result = calculateAnzahlQuorumErreicht(prozentsatz, grundwert);

    if (result > 0) {
      result++;
    }

    return result;
  }

  public long getAnzahlQuorumErreicht(G gebiet) {
    return calculateAnzahlQuorumErreicht(getWahl(), getGrundwert(gebiet));
  }

  public static long calculateAnzahlQuorumErreicht(Wahl wahl, Long grundwert) {
    if (wahl == null) {
      return 0L;
    }

    return calculateAnzahlQuorumErreicht(wahl.getQuorumProzenthuerde(), grundwert);
  }

  public static long calculateAnzahlQuorumErreicht(BigDecimal prozentsatz, Long grundwert) {
    if (prozentsatz == null || grundwert == null) {
      return 0L;
    }

    return calculateQuorumProzentwert(prozentsatz, BigDecimal.valueOf(grundwert));
  }

  private static long calculateQuorumProzentwert(BigDecimal prozentsatz, BigDecimal grundwert) {
    if (prozentsatz == null || grundwert == null) {
      return 0L;
    }

    BigDecimal prozentwert = grundwert.multiply(prozentsatz).divide(BigDecimal.valueOf(100L));

    return prozentwert.setScale(0, RoundingMode.UP).longValue();
  }
}
