
package de.ivu.elect.dokumente;

import static java.util.Arrays.stream;
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.replaceIgnoreCase;
import static org.apache.commons.lang3.StringUtils.startsWithIgnoreCase;
import static org.apache.commons.lang3.StringUtils.trimToEmpty;

import java.io.Serializable;

import javax.annotation.Nullable;

import de.ivu.document.generator.template.annotations.DocumentMethod;
import de.ivu.document.generator.template.annotations.DocumentParam;
import de.ivu.elect.business.system.entity.SystemGebietsebene;

public class CustomParameterDokumentFormatter implements Serializable {

  private static final long serialVersionUID = 1L;

  private final CustomParameterDokument customParameterDokument;

  public CustomParameterDokumentFormatter(CustomParameterDokument customParameterDokument) {
    super();

    this.customParameterDokument = customParameterDokument;
  }

  private SystemGebietsebene getSystemGebietsebene() {
    return customParameterDokument.getSystemGebietsebene();
  }

  private String getWahlbezeichnung() {
    return customParameterDokument.wahlbezeichnung;
  }

  @DocumentMethod
  public String formatWahlbezeichnungImGebiet(@Nullable @DocumentParam("\"gebietName\"") String gebietName) {
    return formatWahlbezeichnungImGebiet(getWahlbezeichnung(), gebietName);
  }

  @DocumentMethod
  public String formatWahlbezeichnungImGebiet(@Nullable @DocumentParam("\"wahlbezeichnungDefault\"") String wahlbezeichnungDefault, @Nullable @DocumentParam("\"gebietName\"") String gebietName) {
    return trimToEmpty(formatWahlbezeichnungImGebietWahlart(wahlbezeichnungDefault) + " " + formatWahlbezeichnungImGebietGebietsebene(gebietName));
  }

  @DocumentMethod
  public String formatWahlbezeichnungImGebietWahlart(@Nullable @DocumentParam("\"wahlbezeichnungDefault\"") String wahlbezeichnungDefault) {
    return defaultIfBlank(getWahlbezeichnung(), trimToEmpty(wahlbezeichnungDefault));
  }

  @DocumentMethod
  public String formatWahlbezeichnungImGebietGebietsebene(@Nullable @DocumentParam("\"gebietName\"") String gebietName) {
    String result = "";

    String gebietBezeichnungName = trimToEmpty(gebietName);

    if (isNotBlank(gebietBezeichnungName)) {
      String gebietBezeichnungPrefix = "in";

      switch (getSystemGebietsebene()) {
        case GEMEINDE :
        case VERBANDSGEMEINDE :
          if (startsWithAnyIgnoreCase(gebietBezeichnungName, "Gemeinde ")) {
            gebietBezeichnungPrefix = "in der";
          } else if (startsWithIgnoreCase(gebietBezeichnungName, "Markt ")) {
            gebietBezeichnungPrefix = "im";
          } else {
            gebietBezeichnungPrefix = "in der Gemeinde";
          }

          break;
        case GEMEINDE_KREISFREI :
          if (startsWithAnyIgnoreCase(gebietBezeichnungName, "kreisfrei")) {
            gebietBezeichnungName = replaceIgnoreCase(gebietBezeichnungName, "kreisfreien Stadt ", "kreisfreien Stadt ");
            gebietBezeichnungName = replaceIgnoreCase(gebietBezeichnungName, "kreisfreie Stadt ", "kreisfreien Stadt ");
          }

          if (startsWithAnyIgnoreCase(gebietBezeichnungName, "kreisfreien Stadt ")) {
            gebietBezeichnungPrefix = "in der";
          } else if (startsWithAnyIgnoreCase(gebietBezeichnungName, "Markt ")) {
            gebietBezeichnungPrefix = "im";
          } else {
            gebietBezeichnungPrefix = "in der kreisfreien Stadt";
          }

          break;
        case LANDKREIS :
          if (startsWithAnyIgnoreCase(gebietBezeichnungName, "Landkreis ", "Kreis ", "Markt ")) {
            gebietBezeichnungPrefix = "im";
          } else {
            gebietBezeichnungPrefix = "im Landkreis";
          }

          break;

        default :
          break;
      }

      result = gebietBezeichnungPrefix + " " + gebietBezeichnungName;
    }

    return result;
  }

  private boolean startsWithAnyIgnoreCase(String value, String one, String... more) {
    return startsWithIgnoreCase(value, one) || stream(more).anyMatch(prefix -> startsWithIgnoreCase(value, prefix));
  }
}
