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

import static de.ivu.elect.business.wahl.entity.WahlartSitzberechnungsalgorithmus.KEIN;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.normalizeSpace;
import static org.apache.commons.lang3.StringUtils.trimToEmpty;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import de.ivu.elect.business.wahl.boundary.WahlartTemplate;

/**
 * Identifiziert Wahlarten, die über einen Kunden hinaus gemeinsamen Wahlart-spezifischen Code verwenden.
 */
public enum CommonWahlart implements WahlartTemplate {

  BUNDESTAGSWAHL {

    @Override
    public boolean isBundestagswahl() {
      return true;
    }

    @Override
    public WahlartSitzberechnungsalgorithmus getSitzberechnungsalgorithmus() {
      return WahlartSitzberechnungsalgorithmus.ELECT_BUNDESTAGSWAHL;
    }
  },
  EUROPAWAHL {

    @Override
    public boolean isEuropawahl() {
      return true;
    }

    @Override
    public WahlartSitzberechnungsalgorithmus getSitzberechnungsalgorithmus() {
      return KEIN;
    }
  },
  VOLKSENTSCHEID {

    @Override
    public WahlartSitzberechnungsalgorithmus getSitzberechnungsalgorithmus() {
      return KEIN;
    }

    @Override
    public boolean isVolksentscheid() {
      return true;
    }
  },
  BUERGERENTSCHEID {

    @Override
    public WahlartSitzberechnungsalgorithmus getSitzberechnungsalgorithmus() {
      return KEIN;
    }

    @Override
    public boolean isBuergerentscheid() {
      return true;
    }
  },
  BUERGERMEISTERWAHL {

    @Override
    public WahlartSitzberechnungsalgorithmus getSitzberechnungsalgorithmus() {
      return WahlartSitzberechnungsalgorithmus.ELECT_ABSOLUTE_MEHRHEITSWAHL;
    }

    @Override
    public boolean isBuergermeisterwahl() {
      return true;
    }
  },
  BEGEHREN {

    @Override
    public WahlartSitzberechnungsalgorithmus getSitzberechnungsalgorithmus() {
      return KEIN;
    }
  },

  /**
   * @deprecated
   * @see ByWahlart#LANDTAGSWAHL
   */
  LANDTAGSWAHL_BAYERN {

    @Override
    public String getWahlartNameNormalized() {
      return "LANDTAGSWAHL";
    }

    @Override
    public WahlartSitzberechnungsalgorithmus getSitzberechnungsalgorithmus() {
      return KEIN;
    }
  },
  /**
   * @deprecated
   * @see ByWahlart#BEZIRKSWAHL
   */
  BEZIRKSWAHL_BAYERN {

    @Override
    public String getWahlartNameNormalized() {
      return "BEZIRKSWAHL";
    }

    @Override
    public WahlartSitzberechnungsalgorithmus getSitzberechnungsalgorithmus() {
      return KEIN;
    }
  },

  KREISTAGSWAHL {

    @Override
    public WahlartSitzberechnungsalgorithmus getSitzberechnungsalgorithmus() {
      return KEIN;
    }
  },
  GEMEINDERATSWAHL {

    @Override
    public WahlartSitzberechnungsalgorithmus getSitzberechnungsalgorithmus() {
      return KEIN;
    }
  },

  UNBEKANNT {

    @Override
    public WahlartSitzberechnungsalgorithmus getSitzberechnungsalgorithmus() {
      return KEIN;
    }
  };

  private static final Map<String, String> WAHLART_NAME_NORMALIZED_PER_WAHLART_NAME = new ConcurrentHashMap<>();

  CommonWahlart() {
  }

  @Override
  public CommonWahlart getCommonWahlart() {
    return this;
  }

  @Override
  public String getWahlartName() {
    return name();
  }

  public String getWahlartNameNormalized() {
    return normalizeWahlartName(name());
  }

  @Override
  public boolean equalsWahlart(Wahlart wahlart) {
    return wahlart != null && equals(wahlart.getCommonWahlart());
  }

  public boolean isEuropawahl() {
    return false;
  }

  public boolean isBundestagswahl() {
    return false;
  }

  public boolean isVolksentscheid() {
    return false;
  }

  public boolean isBuergerentscheid() {
    return false;
  }

  public boolean isBuergermeisterwahl() {
    return false;
  }

  public static String normalizeWahlartName(String value) {
    if (isBlank(value)) {
      return "";
    }

    return WAHLART_NAME_NORMALIZED_PER_WAHLART_NAME.computeIfAbsent(value, wahlartName -> {
      String result = trimToEmpty(wahlartName).toUpperCase();

      result = result.replace("Ä", "AE");
      result = result.replace("Ö", "OE");
      result = result.replace("Ü", "UE");

      // ELECT-11705, Suffix entfernen, "Landtagswahl (Gemeinde)" || "Landtagswahl-Kreis (Kreis)" -> "Landtagswahl"...
      result = result.split("[\\(-]")[0];

      result = normalizeSpace(result).replaceAll("\\s+", "_");

      return result;
    });
  }
}
