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

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

import de.ivu.elect.business.person.entity.Wahlrechtsausschluss;
import de.ivu.elect.business.personenpruefung.control.wahlrecht.WahlrechtStaatsangehoerigkeit;
import de.ivu.elect.business.wahl.boundary.WahlartTemplate;


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;

/**
 * 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 isDirektwahl() {
      return true;
    }
  },
  BEGEHREN {
    @Override
    public WahlartSitzberechnungsalgorithmus getSitzberechnungsalgorithmus() {
      return KEIN;
    }
  },

  /**
   * @see ByWahlart#LANDTAGSWAHL
   * @deprecated
   */
  LANDTAGSWAHL_BAYERN {
    @Override
    public String getWahlartNameNormalized() {
      return "LANDTAGSWAHL";
    }

    @Override
    public WahlartSitzberechnungsalgorithmus getSitzberechnungsalgorithmus() {
      return KEIN;
    }
  },
  /**
   * @see ByWahlart#BEZIRKSWAHL
   * @deprecated
   */
  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;
    }

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

  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 isReferendum() {
    return isVolksentscheid() || isBuergerentscheid();
  }

  public boolean isVolksentscheid() {
    return false;
  }

  public boolean isBuergerentscheid() {
    return false;
  }

  public boolean isDirektwahl() {
    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;
    });
  }

  public Long getKandidatMindestalterAmWahltermin() {
    return 18L;
  }

  public WahlrechtStaatsangehoerigkeit getWahlrechtStaatsangehoerigkeitZugelassen() {
    return WahlrechtStaatsangehoerigkeit.DEUTSCH;
  }

  public List<Wahlrechtsausschluss> getWahlrechtsausschluesseZugelassen() {
    return Collections.singletonList(Wahlrechtsausschluss.KEIN_AUSSCHLUSS);
  }

  public boolean isUnbekannt() {
    return false;
  }
}
