package de.ivu.elect.core.exchange.stimmen.csv.dynamic;

import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;

import javax.annotation.Nullable;

import org.apache.commons.lang3.StringUtils;

import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.stimmeingabe.control.ListenwahlStimmeingabeKonfiguration;
import de.ivu.elect.business.wahl.entity.Wahldurchfuehrung;

public abstract class AbstractDynamicStimmenImportDTOParser {

  private final Wahldurchfuehrung wahldurchfuehrung;

  public AbstractDynamicStimmenImportDTOParser(Wahldurchfuehrung wahldurchfuehrung) {
    this.wahldurchfuehrung = wahldurchfuehrung;
  }

  protected Wahldurchfuehrung getWahldurchfuehrung() {
    return wahldurchfuehrung;
  }

  public abstract Optional<Boolean> isBriefwahlgebiet(DynamicStimmenSource source);

  public abstract String getErfassungsgebietNummer(DynamicStimmenSource source);

  public abstract String getErfassungsgebietName(DynamicStimmenSource source);

  public abstract String getAnzahlWahlberechtigteGesamt(DynamicStimmenSource source);

  public abstract String getAnzahlWahlberechtigteMitWahlschein(DynamicStimmenSource source);

  public abstract String getAnzahlWahlberechtigteOhneWahlschein(DynamicStimmenSource source);

  public abstract String getAnzahlWahlberechtigteNichtImWaehlerverzeichnis(DynamicStimmenSource source);

  public abstract String getAnzahlWaehlerGesamt(DynamicStimmenSource source);

  @Nullable
  public abstract String getAnzahlWaehlerMitWahlschein(DynamicStimmenSource source);

  @Nullable
  public abstract String getAnzahlWaehlerOhneWahlschein(DynamicStimmenSource source);

  public abstract String getUrnenwaehlerMitWahlscheinInUrnenwahllokal(DynamicStimmenSource source);

  public abstract String getBriefwaehlerMitWahlscheinInUrnenwahllokal(DynamicStimmenSource source);

  public abstract String getAnzahlDirektstimmenUngueltig(DynamicStimmenSource source);

  public abstract String getAnzahlDirektstimmenGueltig(DynamicStimmenSource source);

  public abstract String getAnzahlListenstimmenUngueltig(DynamicStimmenSource source);

  public abstract String getAnzahlListenstimmenGueltig(DynamicStimmenSource source);

  public abstract long getAnzahlParteien(DynamicStimmenSource source);

  public abstract String getAnzahlDirektstimmen(int gruppenPositionEinsBasiert, DynamicStimmenSource source);

  /**
   * @param gruppenPositionEinsBasiert
   * @param source
   * @return
   */
  public abstract String getAnzahlListenstimmen(int gruppenPositionEinsBasiert, DynamicStimmenSource source);

  public abstract boolean isErfasst(DynamicStimmenSource source);

  public abstract boolean isAusbleibend(DynamicStimmenSource source);

  public abstract String getGemeindeNummer(DynamicStimmenSource source);

  public boolean isErfasstIn(DynamicStimmenSource source) {
    return StringUtils.isNotBlank(getErfasstInErfassungsgebietNummer(source));
  }

  @Nullable
  public abstract String getErfasstInGemeindeNummer(DynamicStimmenSource source);

  @Nullable
  public abstract String getErfasstInErfassungsgebietNummer(DynamicStimmenSource source);

  @Nullable
  public abstract String getErfasstInErfassungsgebietName(DynamicStimmenSource source);

  @Nullable
  public abstract String getErfasstInErfassungsGebietsArt(DynamicStimmenSource source);

  public abstract Optional<Boolean> isErfasstInBriefwahlgebiet(DynamicStimmenSource source);

  public void validate(DynamicStimmenSource source) {
    // TODO
  }

  public abstract List<String> getCsvColumnHeaders(Wahldurchfuehrungsgebiet wurzelgebiet, Supplier<DynamicStimmenExchangeErgebnisDaten> ergebnisDaten, ListenwahlStimmeingabeKonfiguration listenwahlStimmeingabeKonfiguration);

  public List<String> extractHeader(List<List<String>> content) {
    return content.get(0);
  }

  public int extractErsteZeilennummerContent(List<List<String>> content) {
    return 1;
  }

  protected boolean isNichtVorhanden(String headerKey) {
    return StringUtils.isBlank(headerKey) || !isGroesserNull(headerKey);

  }

  private boolean isGroesserNull(String headerKey) {
    try {
      return Long.parseLong(headerKey) > 0;
    } catch (Exception e) {
      return false;
    }
  }

  protected long findMax(long maxBisher, DynamicStimmenSource source, String prefix) {
    long result = maxBisher;

    for (String s : source.getHeader()) {
      if (s.startsWith(prefix) && s.length() > prefix.length()) {
        try {
          result = Math.max(result, Long.parseLong(s.substring(prefix.length())));
        } catch (Exception e) {
          // ignore
        }
      }
    }

    return result;

  }

  public abstract long getAnzahlListenkandidaturen(int gruppenPositionEinsBasiert, DynamicStimmenSource source);

  public abstract String  getAnzahlListenkandidaturstimmen(int gruppenPositionEinsBasiert, int listenkandidaturPositionEinsBasiert, DynamicStimmenSource source);

  public abstract String  getAnzahlListenStimmenUnveraendert(int gruppenPositionEinsBasiert, DynamicStimmenSource source);

  public abstract String  getAnzahlListenStimmenVeraendert(int gruppenPositionEinsBasiert, DynamicStimmenSource source);

  public abstract String getAnzahlGueltigeVorlagenstimmen(int gruppenPositionEinsBasiert, DynamicStimmenSource source);

  public abstract String getAnzahlUngueltigeVorlagenstimmen(int gruppenPositionEinsBasiert, DynamicStimmenSource source);

  public abstract String getAnzahlReferendumOptionStimmen(int gruppenPosition, long referendumOptionPosition, DynamicStimmenSource source);

  public abstract Long getAnzahlReferendumOptionen(DynamicStimmenSource source, int gruppenPosition);

  public abstract String getErfassungsGebietsArt(DynamicStimmenSource source);
}
