
package de.ivu.elect.business.niederschrift.boundary;

import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.splitByWholeSeparator;
import static org.apache.commons.lang3.StringUtils.substring;
import static org.apache.commons.lang3.StringUtils.trimToEmpty;
import static org.apache.commons.lang3.StringUtils.trimToNull;
import static org.apache.commons.lang3.StringUtils.upperCase;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.function.Function;

import javax.annotation.Nullable;
import javax.inject.Inject;

import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.niederschrift.entity.Niederschrift;
import de.ivu.elect.business.niederschrift.entity.NiederschriftArt;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.presentation.gebietsbaum.GebietNummerFormatter;

public class NiederschriftFormatter {

  @Inject
  private transient GebietNummerFormatter gebietNummerFormatter;

  public NiederschriftFormatter() {
    super();
  }

  @Nullable
  public String formatNiederschriftMitGebiet(Niederschrift niederschrift, Messages messages) {
    if (niederschrift == null) {
      return null;
    }

    return formatAnzeigeNiederschrift(niederschrift, messages) + " " + formatAnzeigeGebiet(niederschrift);
  }

  public String formatAnzeigeNiederschrift(Niederschrift niederschrift, Messages messages) {
    return messages.lokalisiere(niederschrift.getNiederschriftArt());
  }

  public String formatAnzeigeGebiet(Niederschrift niederschrift) {
    return gebietNummerFormatter.getDarstellung(niederschrift.getWahldurchfuehrungsgebiet());
  }

  public NiederschriftKuerzelSchnelleingabe formatKuerzelSchnelleingabeWahlExcluded(Niederschrift niederschrift) {
    return new NiederschriftKuerzelSchnelleingabe(niederschrift, false, this::formatKuerzelSchnelleingabeGebietGebietsart);
  }

  public NiederschriftKuerzelSchnelleingabe formatKuerzelSchnelleingabeWahlIncluded(Niederschrift niederschrift) {
    return new NiederschriftKuerzelSchnelleingabe(niederschrift, true, this::formatKuerzelSchnelleingabeGebietGebietsart);
  }

  public NiederschriftKuerzelSchnelleingabe formatKuerzelSchnelleingabe(String kuerzelSchnelleingabe) {
    return new NiederschriftKuerzelSchnelleingabe(kuerzelSchnelleingabe);
  }

  protected String formatKuerzelSchnelleingabeGebietGebietsart(Niederschrift niederschrift) {
    return niederschrift.getGebiet().getGebietsart().getPosition().toString();
  }

  // ELECTMUC-2796
  public class NiederschriftKuerzelSchnelleingabe {

    private static final String SEPARATOR = "-";

    private static final String VALUE_PART_WAHL_WAHLDATUM_FORMAT = "ddMMyy";

    private final String wahlKennzeichen;

    private final Date wahlWahldatum;

    private final NiederschriftArt niederschriftNiederschriftArt;

    private final String gebietNummer;

    private final String valuePartWahl;

    private final String valuePartWahlKennzeichen;

    private final String valuePartWahlWahldatum;

    private final String valuePartNiederschrift;

    private final String valuePartNiederschriftNiederschriftArtKuerzel;

    private final String valuePartGebiet;

    private final String valuePartGebietGebietsart;

    private final String valuePartGebietNummer;

    private final String value;

    private final String valueFormatted;

    public NiederschriftKuerzelSchnelleingabe(Niederschrift niederschrift, boolean wahlIncluded, Function<Niederschrift, String> valuePartGebietGebietsartFormatter) {
      super();

      Wahl wahl = niederschrift.getWahl();
      Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = niederschrift.getWahldurchfuehrungsgebiet();

      this.wahlKennzeichen = wahl.getKennzeichen();
      this.wahlWahldatum = wahl.getWahldatum();

      this.gebietNummer = wahldurchfuehrungsgebiet.getNummer();

      this.niederschriftNiederschriftArt = niederschrift.getNiederschriftArt();

      this.valuePartWahlKennzeichen = trimToEmpty(this.wahlKennzeichen);
      this.valuePartWahlWahldatum = this.wahlWahldatum == null ? "" : new SimpleDateFormat(VALUE_PART_WAHL_WAHLDATUM_FORMAT).format(this.wahlWahldatum);

      this.valuePartNiederschriftNiederschriftArtKuerzel = this.niederschriftNiederschriftArt == null ? "" : trimToEmpty(this.niederschriftNiederschriftArt.getKuerzel());

      this.valuePartGebietGebietsart = valuePartGebietGebietsartFormatter.apply(niederschrift);
      this.valuePartGebietNummer = trimToEmpty(this.gebietNummer);

      this.valuePartWahl = this.valuePartWahlKennzeichen + this.valuePartWahlWahldatum;
      this.valuePartNiederschrift = this.valuePartNiederschriftNiederschriftArtKuerzel;
      this.valuePartGebiet = this.valuePartGebietGebietsart + SEPARATOR + this.valuePartGebietNummer;

      this.value = (wahlIncluded && isNotBlank(this.valuePartWahl) ? this.valuePartWahl + SEPARATOR : "") + this.valuePartNiederschrift + SEPARATOR + this.valuePartGebiet;
      this.valueFormatted = upperCase(this.value);
    }

    public NiederschriftKuerzelSchnelleingabe(String valueFormatted) {
      super();

      boolean wahlIncluded = false;

      String valuePartWahlKennzeichen = "";
      String valuePartWahlWahldatum = "";

      String valuePartNiederschriftNiederschriftArtKuerzel = "";

      String valuePartGebietGebietsart = "";
      String valuePartGebietNummer = "";

      String[] valueFormattedSplitted = splitByWholeSeparator(valueFormatted, SEPARATOR);

      if (valueFormattedSplitted != null) {
        wahlIncluded = valueFormattedSplitted.length == 4;

        String wahl = valueFormattedSplitted[0];

        if (wahlIncluded) {
          int wahlWahldatumFormatLength = -1 * VALUE_PART_WAHL_WAHLDATUM_FORMAT.length();

          valuePartWahlKennzeichen = substring(wahl, 0, wahlWahldatumFormatLength);
          valuePartWahlWahldatum = substring(wahl, wahlWahldatumFormatLength);

          valuePartGebietGebietsart = valueFormattedSplitted[2];
          valuePartGebietNummer = valueFormattedSplitted[3];

          valuePartNiederschriftNiederschriftArtKuerzel = valueFormattedSplitted[1];
        } else if (valueFormattedSplitted.length == 3) {
          valuePartGebietGebietsart = valueFormattedSplitted[1];
          valuePartGebietNummer = valueFormattedSplitted[2];

          valuePartNiederschriftNiederschriftArtKuerzel = valueFormattedSplitted[0];
        }
      }

      Date wahlWahldatum = null;

      try {
        wahlWahldatum = new SimpleDateFormat(VALUE_PART_WAHL_WAHLDATUM_FORMAT).parse(valuePartWahlWahldatum);
      } catch (Exception ignored) {

      }

      this.wahlKennzeichen = trimToNull(valuePartWahlKennzeichen);
      this.wahlWahldatum = wahlWahldatum;

      NiederschriftArt niederschriftNiederschriftArt = null;

      for (NiederschriftArt niederschriftArt : NiederschriftArt.values()) {
        if (equalsIgnoreCase(niederschriftArt.getKuerzel(), valuePartNiederschriftNiederschriftArtKuerzel)) {
          niederschriftNiederschriftArt = niederschriftArt;

          break;
        }
      }

      this.niederschriftNiederschriftArt = niederschriftNiederschriftArt;

      this.gebietNummer = trimToNull(valuePartGebietNummer);

      this.valuePartWahlKennzeichen = trimToEmpty(this.wahlKennzeichen);
      this.valuePartWahlWahldatum = this.wahlWahldatum == null ? "" : new SimpleDateFormat(VALUE_PART_WAHL_WAHLDATUM_FORMAT).format(this.wahlWahldatum);

      this.valuePartNiederschriftNiederschriftArtKuerzel = this.niederschriftNiederschriftArt == null ? "" : trimToEmpty(this.niederschriftNiederschriftArt.getKuerzel());

      this.valuePartGebietGebietsart = valuePartGebietGebietsart;
      this.valuePartGebietNummer = trimToEmpty(this.gebietNummer);

      this.valuePartWahl = this.valuePartWahlKennzeichen + this.valuePartWahlWahldatum;
      this.valuePartNiederschrift = this.valuePartNiederschriftNiederschriftArtKuerzel;
      this.valuePartGebiet = this.valuePartGebietGebietsart + SEPARATOR + this.valuePartGebietNummer;

      this.value = (wahlIncluded && isNotBlank(this.valuePartWahl) ? this.valuePartWahl + SEPARATOR : "") + this.valuePartNiederschrift + SEPARATOR + this.valuePartGebiet;
      this.valueFormatted = upperCase(this.value);
    }

    public String getValueFormatted() {
      return valueFormatted;
    }

    public String getWahlKennzeichen() {
      return wahlKennzeichen;
    }

    public Date getWahlWahldatum() {
      return wahlWahldatum;
    }

    public String getGebietNummer() {
      return gebietNummer;
    }

    public NiederschriftArt getNiederschriftNiederschriftArt() {
      return niederschriftNiederschriftArt;
    }
  }
}
