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

import java.text.MessageFormat;
import java.util.Collection;

import javax.annotation.Nonnull;
import javax.inject.Inject;

import de.ivu.elect.business.ergebnis.entity.Stimmenart;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebiet;
import de.ivu.elect.business.stimmzettel.entity.EntityAufStimmzettelDaten;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.business.wahlvorschlag.entity.WahlvorschlagStimmzettelPosition;

public class ListenstimmeLabelGenerator extends AbstractStimmeLabelGenerator {

  private static final long serialVersionUID = 1L;

  protected static final String MSG_KEY_INFIX_LISTENSTIMME = Stimmenart.LISTENSTIMME.name();

  protected static final String MSG_KEY_INFIX_LISTENSTIMME_UNBESTIMMT = Stimmenart.LISTENSTIMME_UNBESTIMMT.name();

  @Inject
  private transient ListenkandidaturstimmeLabelGenerator listenkandidaturstimmeLabelGenerator;

  public ListenstimmeLabelGenerator() {
    super();
  }

  public ListenstimmeLabelGenerator(StimmeLabelMessages stimmeLabelMessages) {
    this(stimmeLabelMessages, new ListenkandidaturstimmeLabelGenerator(stimmeLabelMessages));
  }

  public ListenstimmeLabelGenerator(StimmeLabelMessages stimmeLabelMessages, ListenkandidaturstimmeLabelGenerator listenkandidaturstimmeLabelGenerator) {
    super(stimmeLabelMessages);

    this.listenkandidaturstimmeLabelGenerator = listenkandidaturstimmeLabelGenerator;
  }

  public String formatListenstimmeAnzahlUngueltigeGesamtKennung(GruppeImGebiet gruppeImGebiet, Collection<GruppeImGebiet> gruppenImGebiet) {
    return formatListenstimmeAnzahlUngueltigeGesamtKennung(gruppeImGebiet.getGebiet());
  }

  public String formatListenstimmeAnzahlUngueltigeGesamtKennung(Gebiet gebiet) {
    return getListenstimmeAnzahlUngueltigeGesamtKennung(gebiet);
  }

  protected String getListenstimmeAnzahlUngueltigeGesamtKennung(Gebiet gebiet) {
    String msgKeyInfix = MSG_KEY_INFIX_LISTENSTIMME + ".ANZAHL." + MSG_KEY_INFIX_UNGUELTIGE + "." + MSG_KEY_INFIX_GESAMT;

    return getKennungOrDefault(gebiet, msgKeyInfix, "C");
  }

  public String formatListenstimmeAnzahlUngueltigeGesamtBezeichnung(GruppeImGebiet gruppeImGebiet, Collection<GruppeImGebiet> gruppenImGebiet) {
    return getListenstimmeAnzahlUngueltigeGesamtBezeichnung(gruppeImGebiet.getGebiet());
  }

  protected String getListenstimmeAnzahlUngueltigeGesamtBezeichnung(Gebiet gebiet) {
    String defaultValue = "Ungültige Listenstimmen";

    if (isSystemGruppeUngueltigeErfasstAlsStimmzettel(gebiet)) {
      defaultValue = "Ungültige Stimmzettel";
    }

    String msgKeyInfix = MSG_KEY_INFIX_LISTENSTIMME + ".ANZAHL." + MSG_KEY_INFIX_UNGUELTIGE + "." + MSG_KEY_INFIX_GESAMT;

    return getBezeichnungOrDefault(gebiet, msgKeyInfix, defaultValue);
  }

  public String formatListenstimmeAnzahlUnbestimmteGesamtKennung(GruppeImGebiet gruppeImGebiet, Collection<GruppeImGebiet> gruppenImGebiet) {
    return formatListenstimmeAnzahlUnbestimmteGesamtKennung(gruppeImGebiet.getGebiet());
  }

  public String formatListenstimmeAnzahlUnbestimmteGesamtKennung(Gebiet gebiet) {
    return getListenstimmeAnzahlUnbestimmteGesamtKennung(gebiet);
  }

  protected String getListenstimmeAnzahlUnbestimmteGesamtKennung(Gebiet gebiet) {
    String msgKeyInfix = MSG_KEY_INFIX_LISTENSTIMME_UNBESTIMMT + ".ANZAHL." + MSG_KEY_INFIX_UNBESTIMMTE + "." + MSG_KEY_INFIX_GESAMT;

    return getKennungOrDefault(gebiet, msgKeyInfix, "");
  }

  public String formatListenstimmeAnzahlUnbestimmteGesamtBezeichnung(GruppeImGebiet gruppeImGebiet, Collection<GruppeImGebiet> gruppenImGebiet) {
    return getListenstimmeAnzahlUnbestimmteGesamtBezeichnung(gruppeImGebiet.getGebiet());
  }

  protected String getListenstimmeAnzahlUnbestimmteGesamtBezeichnung(Gebiet gebiet) {
    String defaultValue = "Listenstimmen mit Anlass zu Bedenken";

    if (isSystemGruppeUnbestimmteErfasstAlsStimmzettel(gebiet)) {
      defaultValue = "Stimmzettel mit Anlass zu Bedenken";
    }

    String msgKeyInfix = MSG_KEY_INFIX_LISTENSTIMME_UNBESTIMMT + ".ANZAHL." + MSG_KEY_INFIX_UNBESTIMMTE + "." + MSG_KEY_INFIX_GESAMT;

    return getBezeichnungOrDefault(gebiet, msgKeyInfix, defaultValue);
  }

  public String formatListenstimmeAnzahlGueltigeGesamtKennung(GruppeImGebiet gruppeImGebiet, Collection<GruppeImGebiet> gruppenImGebiet) {
    return formatListenstimmeAnzahlGueltigeGesamtKennung(gruppeImGebiet.getGebiet());
  }

  public String formatListenstimmeAnzahlGueltigeGesamtKennung(Gebiet gebiet) {
    return getListenstimmeAnzahlGueltigeGesamtKennung(gebiet);
  }

  protected String getListenstimmeAnzahlGueltigeGesamtKennung(Gebiet gebiet) {
    String msgKeyInfix = MSG_KEY_INFIX_LISTENSTIMME + ".ANZAHL." + MSG_KEY_INFIX_GUELTIGE + "." + MSG_KEY_INFIX_GESAMT;

    return getKennungOrDefault(gebiet, msgKeyInfix, "D");
  }

  public String formatListenstimmeAnzahlGueltigeGesamtBezeichnung(GruppeImGebiet gruppeImGebiet, Collection<GruppeImGebiet> gruppenImGebiet) {
    return getListenstimmeAnzahlGueltigeGesamtBezeichnung(gruppeImGebiet.getGebiet());
  }

  protected String getListenstimmeAnzahlGueltigeGesamtBezeichnung(Gebiet gebiet) {
    String defaultValue = "Gültige Listenstimmen";

    if (isSystemGruppeGueltigeErfasstAlsStimmzettel(gebiet)) {
      defaultValue = "Gültige Stimmzettel";
    }

    String msgKeyInfix = MSG_KEY_INFIX_LISTENSTIMME + ".ANZAHL." + MSG_KEY_INFIX_GUELTIGE + "." + MSG_KEY_INFIX_GESAMT;

    return getBezeichnungOrDefault(gebiet, msgKeyInfix, defaultValue);
  }

  public String formatListenstimmeAnzahlGueltigeGruppeBezeichnung(EntityAufStimmzettelDaten entityAufStimmzettelDaten, GruppeImGebiet gruppeImGebiet, Collection<GruppeImGebiet> gruppenImGebiet) {
    return getWahlvorschlagStimmzettelKurzname(entityAufStimmzettelDaten, gruppeImGebiet);
  }

  public String formatListenstimmeAnzahlGueltigeKennungFortlaufend(EntityAufStimmzettelDaten entityAufStimmzettelDaten, long positionFortlaufend, GruppeImGebiet gruppeImGebiet) {
    if (isGruppeImGebietFuerWaehlerBenannteKandidaturen(gruppeImGebiet)) {
      return formatListenstimmeAnzahlGueltigeFuerWaehlerBenannteKandidaturenKennungFortlaufend(entityAufStimmzettelDaten, positionFortlaufend, gruppeImGebiet);
    }

    return format(getListenstimmeAnzahlGueltigeKennungFortlaufend(gruppeImGebiet.getGebiet()), positionFortlaufend, getWahlvorschlagStimmzettelKurzname(entityAufStimmzettelDaten, gruppeImGebiet));
  }

  private String formatListenstimmeAnzahlGueltigeFuerWaehlerBenannteKandidaturenKennungFortlaufend(EntityAufStimmzettelDaten entityAufStimmzettelDaten, long positionFortlaufend,
      GruppeImGebiet gruppeImGebiet) {
    return "";
  }

  protected String getListenstimmeAnzahlGueltigeKennungFortlaufend(Gebiet gebiet) {
    String msgKeyInfix = MSG_KEY_INFIX_LISTENSTIMME + ".ANZAHL." + MSG_KEY_INFIX_GUELTIGE;

    return getKennungFortlaufendOrDefault(gebiet, msgKeyInfix, "D{0}");
  }

  public String formatListenstimmeAnzahlGueltigeKennung(EntityAufStimmzettelDaten entityAufStimmzettelDaten, GruppeImGebiet gruppeImGebiet, Collection<GruppeImGebiet> gruppenImGebiet) {
    return formatListenstimmeAnzahlGueltigeKennung(entityAufStimmzettelDaten, gruppeImGebiet, getWahlvorschlagStimmzettelPosition(entityAufStimmzettelDaten, gruppeImGebiet, gruppenImGebiet));
  }

  @Override
  protected WahlvorschlagStimmzettelPosition bestimmeStimmzettelPosition(EntityAufStimmzettelDaten entityAufStimmzettelDaten, @Nonnull GruppeImGebiet gruppeImGebiet) {
    Liste ersteListeAbgeleitet = gruppeImGebiet.getErsteListeAbgeleitet(entityAufStimmzettelDaten); // ELECT-12180

    if (ersteListeAbgeleitet == null) {
      return super.bestimmeStimmzettelPosition(entityAufStimmzettelDaten, gruppeImGebiet);
    }

    return ersteListeAbgeleitet.getStimmzettelPosition(/* ELECT-12217 */ gruppeImGebiet.getGebiet(), entityAufStimmzettelDaten);
  }

  public String formatListenstimmeAnzahlGueltigeKennung(EntityAufStimmzettelDaten entityAufStimmzettelDaten, GruppeImGebiet gruppeImGebiet,
      WahlvorschlagStimmzettelPosition wahlvorschlagStimmzettelPosition) {
    if (isGruppeImGebietFuerWaehlerBenannteKandidaturen(gruppeImGebiet)) {
      return formatListenstimmeAnzahlGueltigeFuerWaehlerBenannteKandidaturenKennung(entityAufStimmzettelDaten, gruppeImGebiet, wahlvorschlagStimmzettelPosition);
    }

    return format(getListenstimmeAnzahlGueltigeKennung(gruppeImGebiet.getGebiet()), entityAufStimmzettelDaten, gruppeImGebiet, wahlvorschlagStimmzettelPosition);
  }

  private String formatListenstimmeAnzahlGueltigeFuerWaehlerBenannteKandidaturenKennung(EntityAufStimmzettelDaten entityAufStimmzettelDaten, GruppeImGebiet gruppeImGebiet,
      WahlvorschlagStimmzettelPosition wahlvorschlagStimmzettelPosition) {
    return "";
  }

  protected String getListenstimmeAnzahlGueltigeKennung(Gebiet gebiet) {
    String msgKeyInfix = MSG_KEY_INFIX_LISTENSTIMME + ".ANZAHL." + MSG_KEY_INFIX_GUELTIGE;

    return getKennungOrDefault(gebiet, msgKeyInfix, "D{0}");
  }

  public String formatListenstimmeAnzahlGueltigeBezeichnung(EntityAufStimmzettelDaten entityAufStimmzettelDaten, GruppeImGebiet gruppeImGebiet, Collection<GruppeImGebiet> gruppenImGebiet) {
    return format(getListenstimmeAnzahlGueltigeBezeichnung(gruppeImGebiet.getGebiet()), entityAufStimmzettelDaten, gruppeImGebiet, gruppenImGebiet);
  }

  protected String getListenstimmeAnzahlGueltigeBezeichnung(Gebiet gebiet) {
    String msgKeyInfix = MSG_KEY_INFIX_LISTENSTIMME + ".ANZAHL." + MSG_KEY_INFIX_GUELTIGE;

    return getBezeichnungOrDefault(gebiet, msgKeyInfix, "{1}");
  }

  public String formatListenstimmeAnzahlAbgegebeneKennung(EntityAufStimmzettelDaten entityAufStimmzettelDaten, GruppeImGebiet gruppeImGebiet, Collection<GruppeImGebiet> gruppenImGebiet) {
    return format(getListenstimmeAnzahlAbgegebeneKennung(gruppeImGebiet.getGebiet()), entityAufStimmzettelDaten, gruppeImGebiet, gruppenImGebiet);
  }

  protected String getListenstimmeAnzahlAbgegebeneKennung(Gebiet gebiet) {
    String msgKeyInfix = MSG_KEY_INFIX_LISTENSTIMME + ".ANZAHL." + MSG_KEY_INFIX_ABGEGEBENE;

    return getKennungOrDefault(gebiet, msgKeyInfix, "");
  }

  protected String getListenstimmeAnzahlAbgegebeneBezeichnung(Gebiet gebiet) {
    String defaultValue = "Abgegebene Listenstimmen insgesamt";

    if (isSystemGruppeGueltigeErfasstAlsStimmzettel(gebiet)) {
      if (isSystemGruppeUngueltigeErfasstAlsStimmzettel(gebiet)) {
        defaultValue = "Abgegebene Stimmzettel insgesamt";
      } else {
        defaultValue = "";
      }
    }

    String msgKeyInfix = MSG_KEY_INFIX_LISTENSTIMME + ".ANZAHL." + MSG_KEY_INFIX_ABGEGEBENE;

    return getBezeichnungOrDefault(gebiet, msgKeyInfix, defaultValue);
  }

  public String formatListenstimmeAnzahlAbgegebeneGesamtKennung(EntityAufStimmzettelDaten entityAufStimmzettelDaten, GruppeImGebiet gruppeImGebiet, Collection<GruppeImGebiet> gruppenImGebiet) {
    return format(getListenstimmeAnzahlAbgegebeneGesamtKennung(gruppeImGebiet.getGebiet()), entityAufStimmzettelDaten, gruppeImGebiet, gruppenImGebiet);
  }

  public String formatListenstimmeAnzahlAbgegebeneGesamtKennung(Gebiet gebiet) {
    return getListenstimmeAnzahlAbgegebeneGesamtKennung(gebiet);
  }

  protected String getListenstimmeAnzahlAbgegebeneGesamtKennung(Gebiet gebiet) {
    String msgKeyInfix = MSG_KEY_INFIX_LISTENSTIMME + ".ANZAHL." + MSG_KEY_INFIX_ABGEGEBENE + "." + MSG_KEY_INFIX_GESAMT;

    return getKennungOrDefault(gebiet, msgKeyInfix, "");
  }

  public String formatListenstimmeAnzahlAbgegebeneGesamtBezeichnung(EntityAufStimmzettelDaten entityAufStimmzettelDaten, GruppeImGebiet gruppeImGebiet, Collection<GruppeImGebiet> gruppenImGebiet) {
    return format(getListenstimmeAnzahlAbgegebeneGesamtBezeichnung(gruppeImGebiet.getGebiet()), entityAufStimmzettelDaten, gruppeImGebiet, gruppenImGebiet);
  }

  protected String getListenstimmeAnzahlAbgegebeneGesamtBezeichnung(Gebiet gebiet) {
    String defaultValue = "Abgegebene Listenstimmen insgesamt";

    if (isSystemGruppeGueltigeErfasstAlsStimmzettel(gebiet)) {
      if (isSystemGruppeUngueltigeErfasstAlsStimmzettel(gebiet)) {
        defaultValue = "Abgegebene Stimmzettel insgesamt";
      } else {
        defaultValue = "";
      }
    }

    String msgKeyInfix = MSG_KEY_INFIX_LISTENSTIMME + ".ANZAHL." + MSG_KEY_INFIX_ABGEGEBENE + "." + MSG_KEY_INFIX_GESAMT;

    return getBezeichnungOrDefault(gebiet, msgKeyInfix, defaultValue);
  }

  private String format(String pattern, EntityAufStimmzettelDaten entityAufStimmzettelDaten, GruppeImGebiet gruppeImGebiet, Collection<GruppeImGebiet> gruppenImGebiet) {
    return format(pattern, entityAufStimmzettelDaten, gruppeImGebiet, getWahlvorschlagStimmzettelPosition(entityAufStimmzettelDaten, gruppeImGebiet, gruppenImGebiet));
  }

  private String format(String pattern, EntityAufStimmzettelDaten entityAufStimmzettelDaten, GruppeImGebiet gruppeImGebiet, WahlvorschlagStimmzettelPosition wahlvorschlagStimmzettelPosition) {
    return format(pattern, wahlvorschlagStimmzettelPosition, getWahlvorschlagStimmzettelKurzname(entityAufStimmzettelDaten, gruppeImGebiet));
  }

  private String format(String pattern, WahlvorschlagStimmzettelPosition wahlvorschlagStimmzettelPosition, String wahlvorschlagStimmzettelKurzname) {
    return format(pattern, fixNullToZero(wahlvorschlagStimmzettelPosition), wahlvorschlagStimmzettelKurzname);
  }

  private String format(String pattern, Long position, String kurzname) {
    return MessageFormat.format(pattern, fixNullToZero(position), fixNullToEmpty(kurzname));
  }

  public ListenkandidaturstimmeLabelGenerator getListenkandidaturstimmeLabelGenerator() {
    return listenkandidaturstimmeLabelGenerator;
  }
}
