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

import static java.util.Collections.emptyMap;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.function.Supplier;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.anschrift.entity.Anschrift;
import de.ivu.elect.business.anschrift.entity.AnschriftArt;
import de.ivu.elect.business.datei.entity.FileType;
import de.ivu.elect.business.dokumente.control.ElectDokumentContext;
import de.ivu.elect.business.eml.control.EmlHashCode;
import de.ivu.elect.business.ergebnis.control.ErgebnisExchangeContext;
import de.ivu.elect.business.exchange.control.FileFormat;
import de.ivu.elect.business.gebietsbaum.boundary.AbstractGebietDAO;
import de.ivu.elect.business.gebietsbaum.control.EntityMitWurzelgebietDAO;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.GebietTK;
import de.ivu.elect.business.gebietsbaum.entity.NlGebietsart;
import de.ivu.elect.business.kandidatur.control.StimmzettelFormatterKandidaturFormatDarstellung;
import de.ivu.elect.business.wahl.boundary.NlExportArtefaktNachSystemExportstatus;
import de.ivu.elect.business.wahl.boundary.NlExportArtefaktNachSystemExportstatusHashCode;
import de.ivu.elect.business.wahl.entity.AbstractWahlParameterLoader;
import de.ivu.elect.business.wahl.entity.NlWahlParameterWerte;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.jee.entity.customdata.EmptyCustomData;
import de.ivu.elect.presentation.gebietsbaum.form.NlZipProperty;

public abstract class AbstractNlExportArtefaktNachSystemExportstatusExportContext extends ElectDokumentContext {

  private static final long serialVersionUID = 1L;

  protected static final Logger LOG = LoggerFactory.getLogger(AbstractNlExportArtefaktNachSystemExportstatusExportContext.class);

  public static final String PARAM_KEY_ARTEFAKT_IN_DATEI_EXPORT_PER_FILE_FORMAT = "AbstractNlExportArtefaktNachSystemExportstatusExportContext#PARAM_KEY_ARTEFAKT_IN_DATEI_EXPORT_PER_FILE_FORMAT";

  public static final String PARAM_KEY_TARGET_FILE_TYPE = "AbstractNlExportArtefaktNachSystemExportstatusExportContext#PARAM_KEY_TARGET_FILE_TYPE";

  public static final String PARAM_KEY_HASH_CODES_PER_FILE_FORMAT = "AbstractNlExportArtefaktNachSystemExportstatusExportContext#PARAM_KEY_HASH_CODES_PER_FILE_FORMAT";

  public static final String WAHLBEHOERDE_SEPARATOR_MSG_KEY = "entity.einzahl.WAHL.WAHLBEHOERDE";

  public static final NlWahlParameterWerte WAHLBEHOERRDE_WAHLLEITER_NAME = NlWahlParameterWerte.WAHLBEHOERRDE_WAHLLEITER_NAME;

  public static final NlWahlParameterWerte WAHLBEHOERDE_ANSCHRIFT_STRASSE_HAUSNUMMER = NlWahlParameterWerte.WAHLBEHOERDE_ANSCHRIFT_STRASSE_HAUSNUMMER;

  public static final NlWahlParameterWerte WAHLBEHOERDE_ANSCHRIFT_ORT = NlWahlParameterWerte.WAHLBEHOERDE_ANSCHRIFT_ORT;

  public static final NlWahlParameterWerte WAHLBEHOERDE_ANSCHRIFT_PLZ = NlWahlParameterWerte.WAHLBEHOERDE_ANSCHRIFT_PLZ;

  public static final String GEWAEHLTES_GREMIUM_SEPARATOR_MSG_KEY = "entity.einzahl.WAHL.GEWAEHLTES_GREMIUM";

  public static final NlWahlParameterWerte GEWAEHLTES_GREMIUM_ANSCHRIFT_STRASSE_HAUSNUMMER = NlWahlParameterWerte.GEWAEHLTES_GREMIUM_ANSCHRIFT_STRASSE_HAUSNUMMER;

  public static final NlWahlParameterWerte GEWAEHLTES_GREMIUM_ANSCHRIFT_ORT = NlWahlParameterWerte.GEWAEHLTES_GREMIUM_ANSCHRIFT_ORT;

  public static final NlWahlParameterWerte GEWAEHLTES_GREMIUM_ANSCHRIFT_PLZ = NlWahlParameterWerte.GEWAEHLTES_GREMIUM_ANSCHRIFT_PLZ;

  public static final String WAHLAUSSCHUSSSITZUNG_SEPARATOR_MSG_KEY = "entity.einzahl.WAHL.WAHLAUSSCHUSSSITZUNG";

  public static final NlWahlParameterWerte WAHLAUSSCHUSSSITZUNG_ANSCHRIFT_STRASSE_HAUSNUMMER = NlWahlParameterWerte.WAHLAUSSCHUSSSITZUNG_ANSCHRIFT_STRASSE_HAUSNUMMER;

  public static final NlWahlParameterWerte WAHLAUSSCHUSSSITZUNG_ANSCHRIFT_ORT = NlWahlParameterWerte.WAHLAUSSCHUSSSITZUNG_ANSCHRIFT_ORT;

  public static final NlWahlParameterWerte WAHLAUSSCHUSSSITZUNG_ANSCHRIFT_PLZ = NlWahlParameterWerte.WAHLAUSSCHUSSSITZUNG_ANSCHRIFT_PLZ;

  public static final String WAHLAUSSCHUSSSITZUNG_BEGINN_ENDE_LABEL_MSG_KEY = NlWahlParameterWerte.WAHLAUSSCHUSSSITZUNG_BEGINN_ENDE_LABEL_MSG_KEY;

  public static final NlWahlParameterWerte WAHLAUSSCHUSSSITZUNG_BEGINN = NlWahlParameterWerte.WAHLAUSSCHUSSSITZUNG_BEGINN;

  public static final String WAHLAUSSCHUSSSITZUNG_BEGINN_DATUM_LABEL_MSG_KEY = NlWahlParameterWerte.WAHLAUSSCHUSSSITZUNG_BEGINN_DATUM_LABEL_MSG_KEY;

  public static final String WAHLAUSSCHUSSSITZUNG_BEGINN_UHRZEIT_LABEL_MSG_KEY = NlWahlParameterWerte.WAHLAUSSCHUSSSITZUNG_BEGINN_UHRZEIT_LABEL_MSG_KEY;

  public static final NlWahlParameterWerte WAHLAUSSCHUSSSITZUNG_ENDE = NlWahlParameterWerte.WAHLAUSSCHUSSSITZUNG_ENDE;

  public static final String WAHLAUSSCHUSSSITZUNG_ENDE_DATUM_LABEL_MSG_KEY = NlWahlParameterWerte.WAHLAUSSCHUSSSITZUNG_ENDE_DATUM_LABEL_MSG_KEY;

  public static final String WAHLAUSSCHUSSSITZUNG_ENDE_UHRZEIT_LABEL_MSG_KEY = NlWahlParameterWerte.WAHLAUSSCHUSSSITZUNG_ENDE_UHRZEIT_LABEL_MSG_KEY;

  public static final NlWahlParameterWerte WAHLAUSSCHUSSSITZUNG_EINWAENDE = NlWahlParameterWerte.WAHLAUSSCHUSSSITZUNG_EINWAENDE;

  public static final NlWahlParameterWerte WAHLAUSSCHUSSSITZUNG_EINWAENDE_BEMERKUNGEN = NlWahlParameterWerte.WAHLAUSSCHUSSSITZUNG_EINWAENDE_BEMERKUNGEN;

  public static final String WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER_SEPARATOR_MSG_KEY = "entity.einzahl.WAHL.WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER";

  public static final NlWahlParameterWerte WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER_1_NAME = NlWahlParameterWerte.WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER_1_NAME;

  public static final NlWahlParameterWerte WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER_1_ROLLE = NlWahlParameterWerte.WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER_1_ROLLE;

  public static final NlWahlParameterWerte WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER_2_NAME = NlWahlParameterWerte.WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER_2_NAME;

  public static final NlWahlParameterWerte WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER_2_ROLLE = NlWahlParameterWerte.WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER_2_ROLLE;

  public static final String FRIST_ZULETZT_GESETZT_SEPARATOR_MSG_KEY = "entity.einzahl.WAHL.FRIST_ZULETZT_GESETZT";

  public static final String FRIST_ZULETZT_GESETZT_BEGINN_ENDE_LABEL_MSG_KEY = NlWahlParameterWerte.FRIST_ZULETZT_GESETZT_BEGINN_ENDE_LABEL_MSG_KEY;

  public static final NlWahlParameterWerte FRIST_ZULETZT_GESETZT_BEGINN = NlWahlParameterWerte.FRIST_ZULETZT_GESETZT_BEGINN;

  public static final String FRIST_ZULETZT_GESETZT_BEGINN_DATUM_LABEL_MSG_KEY = NlWahlParameterWerte.FRIST_ZULETZT_GESETZT_BEGINN_DATUM_LABEL_MSG_KEY;

  public static final String FRIST_ZULETZT_GESETZT_BEGINN_UHRZEIT_LABEL_MSG_KEY = NlWahlParameterWerte.FRIST_ZULETZT_GESETZT_BEGINN_UHRZEIT_LABEL_MSG_KEY;

  public static final NlWahlParameterWerte FRIST_ZULETZT_GESETZT_ENDE = NlWahlParameterWerte.FRIST_ZULETZT_GESETZT_ENDE;

  public static final String FRIST_ZULETZT_GESETZT_ENDE_DATUM_LABEL_MSG_KEY = NlWahlParameterWerte.FRIST_ZULETZT_GESETZT_ENDE_DATUM_LABEL_MSG_KEY;

  public static final String FRIST_ZULETZT_GESETZT_ENDE_UHRZEIT_LABEL_MSG_KEY = NlWahlParameterWerte.FRIST_ZULETZT_GESETZT_ENDE_UHRZEIT_LABEL_MSG_KEY;

  public static final String WAHLVORSCHLAG_EINREICHUNG_SEPARATOR_MSG_KEY = "entity.einzahl.WAHL.WAHLVORSCHLAG_EINREICHUNG";

  public static final NlWahlParameterWerte WAHLVORSCHLAG_EINREICHUNG_ABGABEFRIST = NlWahlParameterWerte.WAHLVORSCHLAG_EINREICHUNG_ABGABEFRIST;

  public static final NlWahlParameterWerte WAHLVORSCHLAG_EINREICHUNG_ANSCHRIFT_ORT = NlWahlParameterWerte.WAHLVORSCHLAG_EINREICHUNG_ANSCHRIFT_ORT;

  public static final String WAHLVORSCHLAG_EINREICHUNG_UNTERZEICHNER_SEPARATOR_MSG_KEY = "entity.einzahl.WAHL.WAHLVORSCHLAG_EINREICHUNG_UNTERZEICHNER";

  public static final NlWahlParameterWerte WAHLVORSCHLAG_EINREICHUNG_UNTERZEICHNER_1_NAME = NlWahlParameterWerte.WAHLVORSCHLAG_EINREICHUNG_UNTERZEICHNER_1_NAME;

  public static final String WAHLVORSCHLAG_VEROEFFENTLICHUNG_SEPARATOR_MSG_KEY = "entity.einzahl.WAHL.WAHLVORSCHLAG_VEROEFFENTLICHUNG";

  public static final NlWahlParameterWerte WAHLVORSCHLAG_VEROEFFENTLICHUNG_BEGINN = NlWahlParameterWerte.WAHLVORSCHLAG_VEROEFFENTLICHUNG_BEGINN;

  public static final NlWahlParameterWerte WAHLVORSCHLAG_VEROEFFENTLICHUNG_ANSCHRIFT_ORT = NlWahlParameterWerte.WAHLVORSCHLAG_VEROEFFENTLICHUNG_ANSCHRIFT_ORT;

  public static final String WAHLVORSCHLAG_VEROEFFENTLICHUNG_UNTERZEICHNER_SEPARATOR_MSG_KEY = "entity.einzahl.WAHL.WAHLVORSCHLAG_VEROEFFENTLICHUNG_UNTERZEICHNER";

  public static final NlWahlParameterWerte WAHLVORSCHLAG_VEROEFFENTLICHUNG_UNTERZEICHNER_1_NAME = NlWahlParameterWerte.WAHLVORSCHLAG_VEROEFFENTLICHUNG_UNTERZEICHNER_1_NAME;

  private final Map<FileFormat, NlExportArtefaktNachSystemExportstatus> artefaktInDateiExportPerFileFormat;

  private final Map<FileFormat, Collection<NlExportArtefaktNachSystemExportstatusHashCode>> hashCodesPerFileFormat;

  private String wahlbehoerdeWahlleiterName;

  private String wahlbehoerdeAnschriftStrasseHausnummer;

  private String wahlbehoerdeAnschriftOrt;

  private String wahlbehoerdeAnschriftPlz;

  private String gewaehltesGremiumAnschriftStrasseHausnummer;

  private String gewaehltesGremiumAnschriftOrt;

  private String gewaehltesGremiumAnschriftPlz;

  private String wahlausschusssitzungAnschriftStrasseHausnummer;

  private String wahlausschusssitzungAnschriftOrt;

  private String wahlausschusssitzungAnschriftPlz;

  private Date wahlausschusssitzungBeginn;

  private Date wahlausschusssitzungEnde;

  private String wahlausschusssitzungEinwaende;

  private String wahlausschusssitzungEinwaendeBemerkungen;

  private String wahlausschusssitzungUnterzeichner1Name;

  private String wahlausschusssitzungUnterzeichner1Rolle;

  private String wahlausschusssitzungUnterzeichner2Name;

  private String wahlausschusssitzungUnterzeichner2Rolle;

  private Date fristZuletztGesetztBeginn;

  private Date fristZuletztGesetztEnde;

  private Date wahlvorschlagEinreichungAbgabefrist;

  private String wahlvorschlagEinreichungAnschriftOrt;

  private String wahlvorschlagEinreichungUnterzeichner1Name;

  private Date wahlvorschlagVeroeffentlichungBeginn;

  private String wahlvorschlagVeroeffentlichungAnschriftOrt;

  private String wahlvorschlagVeroeffentlichungUnterzeichner1Name;

  public AbstractNlExportArtefaktNachSystemExportstatusExportContext(ElectDokumentContext electDokumentContext, AbstractWahlParameterLoader wahlParameterLoader, Collection<Gebiet> gebieteInWahl) {
    super(electDokumentContext);

    this.artefaktInDateiExportPerFileFormat = new HashMap<>();
    this.artefaktInDateiExportPerFileFormat.putAll(electDokumentContext.getOrDefault(PARAM_KEY_ARTEFAKT_IN_DATEI_EXPORT_PER_FILE_FORMAT, Map.class, emptyMap()));

    this.hashCodesPerFileFormat = new HashMap<>();
    this.hashCodesPerFileFormat.putAll(electDokumentContext.getOrDefault(PARAM_KEY_HASH_CODES_PER_FILE_FORMAT, Map.class, emptyMap())); // ELECT-10233

    copyFrom(electDokumentContext.getWahl(), wahlParameterLoader);

    if (isBlank(this.wahlausschusssitzungAnschriftOrt)) { // ELECT-10441
      this.wahlausschusssitzungAnschriftOrt = getGebietCsb(() -> gebieteInWahl).map(Gebiet::getName).orElse("");
    }
  }

  // ELECT-11350
  public void resetBeforeExport() {
    this.artefaktInDateiExportPerFileFormat.clear();

    this.hashCodesPerFileFormat.clear();
  }

  public Optional<FileType> getTargetFileType() {
    return Optional.ofNullable(get(PARAM_KEY_TARGET_FILE_TYPE, FileType.class));
  }

  public void setTargetFileType(FileType targetFileType) {
    put(PARAM_KEY_TARGET_FILE_TYPE, targetFileType);
  }

  // ELECTVAPP-794, ELECTVAPP-795
  public void addArtefaktInDateiExport(NlExportArtefaktNachSystemExportstatus artefakt) {
    if (artefakt != null) {
      artefaktInDateiExportPerFileFormat.put(artefakt.getFileFormat(), artefakt);

      put(PARAM_KEY_ARTEFAKT_IN_DATEI_EXPORT_PER_FILE_FORMAT, artefaktInDateiExportPerFileFormat);
    }
  }

  public Collection<NlExportArtefaktNachSystemExportstatus> getArtefakteInDateiExport() {
    return artefaktInDateiExportPerFileFormat.values();
  }

  public Map<FileFormat, Collection<NlExportArtefaktNachSystemExportstatusHashCode>> getHashCodesPerFileFormat() {
    return hashCodesPerFileFormat;
  }

  // ELECT-10233
  public void addHashCodesPerFileFormat(FileFormat fileFormat, String key, Object value) {
    hashCodesPerFileFormat.putIfAbsent(fileFormat, new HashSet<>());

    if (value != null) {
      try {
        Collection<NlExportArtefaktNachSystemExportstatusHashCode> hashCodes = hashCodesPerFileFormat.get(fileFormat);

        if (EmlHashCode.EML_EXPORT_LAST_HASHCODE_KEY.equals(key)) {
          String hashCode = (String) value;

          if (isNotBlank(hashCode)) {
            hashCodes.add(new NlExportArtefaktNachSystemExportstatusHashCode(fileFormat, hashCode));

            LOG.info("Uebernehme Hash-Code aus Parameter '{}' [fileFormat = {}, hashCode = {}]", key, fileFormat, hashCode);
          }
        } else if (EmlHashCode.EML_EXPORT_HASHCODE_KEY_PRO_GEBIET.equals(key)) {
          for (Entry<GebietTK, String> entry : ((Map<GebietTK, String>) value).entrySet()) {
            GebietTK gebietTk = entry.getKey();
            String hashCode = entry.getValue();

            if (gebietTk != null || isNotBlank(hashCode)) {
              hashCodes.add(new NlExportArtefaktNachSystemExportstatusHashCode(fileFormat, gebietTk, hashCode));

              LOG.info("Uebernehme Hash-Code aus Parameter '{}' [fileFormat = {}, gebiet = {}, hashCode = {}]", key, fileFormat, gebietTk, hashCode);
            }
          }
        }
      } catch (Exception ex) {
        LOG.error("Fehler bei der Uebernahme der Hash-Code-Context-Parameter", ex);
      }
    }

    put(PARAM_KEY_HASH_CODES_PER_FILE_FORMAT, hashCodesPerFileFormat);
  }

  public Gebiet getWurzelgebiet(AbstractGebietDAO gebietDAO) {
    return getWahl().getWurzelgebiet(EntityMitWurzelgebietDAO.fromDao(gebietDAO));
  }

  public Optional<Gebiet> getGebietCsb(AbstractGebietDAO gebietDAO) {
    return getGebietCsb(() -> gebietDAO.findByWahl(getWahl()));
  }

  private Optional<Gebiet> getGebietCsb(Supplier<Collection<Gebiet>> gebieteInWahlFinder) {
    Collection<Gebiet> gebieteInWahl = gebieteInWahlFinder.get();

    return gebieteInWahl.stream().filter(gebiet -> NlGebietsart.isCsb(gebiet, gebieteInWahl)).findFirst();
  }

  public String getWahlbehoerdeWahlleiterName() {
    return wahlbehoerdeWahlleiterName;
  }

  public void setWahlbehoerdeWahlleiterName(String wahlbehoerdeWahlleiterName) {
    this.wahlbehoerdeWahlleiterName = wahlbehoerdeWahlleiterName;
  }

  public Anschrift getWahlbehoerdeAnschrift() {
    return createAnschrift(getWahlbehoerdeAnschriftStrasseHausnummer(), getWahlbehoerdeAnschriftPlz(), getWahlbehoerdeAnschriftOrt());
  }

  public String getWahlbehoerdeAnschriftStrasseHausnummer() {
    return wahlbehoerdeAnschriftStrasseHausnummer;
  }

  public void setWahlbehoerdeAnschriftStrasseHausnummer(String wahlbehoerdeAnschriftStrasseHausnummer) {
    this.wahlbehoerdeAnschriftStrasseHausnummer = wahlbehoerdeAnschriftStrasseHausnummer;
  }

  public String getWahlbehoerdeAnschriftOrt() {
    return wahlbehoerdeAnschriftOrt;
  }

  public void setWahlbehoerdeAnschriftOrt(String wahlbehoerdeAnschriftOrt) {
    this.wahlbehoerdeAnschriftOrt = wahlbehoerdeAnschriftOrt;
  }

  public String getWahlbehoerdeAnschriftPlz() {
    return wahlbehoerdeAnschriftPlz;
  }

  public void setWahlbehoerdeAnschriftPlz(String wahlbehoerdeAnschriftPlz) {
    this.wahlbehoerdeAnschriftPlz = NlZipProperty.formatZip(wahlbehoerdeAnschriftPlz);
  }

  public Anschrift getGewaehltesGremiumAnschrift() {
    return createAnschrift(getGewaehltesGremiumAnschriftStrasseHausnummer(), getGewaehltesGremiumAnschriftPlz(), getGewaehltesGremiumAnschriftOrt());
  }

  public String getGewaehltesGremiumAnschriftStrasseHausnummer() {
    return gewaehltesGremiumAnschriftStrasseHausnummer;
  }

  public void setGewaehltesGremiumAnschriftStrasseHausnummer(String gewaehltesGremiumAnschriftStrasseHausnummer) {
    this.gewaehltesGremiumAnschriftStrasseHausnummer = gewaehltesGremiumAnschriftStrasseHausnummer;
  }

  public String getGewaehltesGremiumAnschriftOrt() {
    return gewaehltesGremiumAnschriftOrt;
  }

  public void setGewaehltesGremiumAnschriftOrt(String gewaehltesGremiumAnschriftOrt) {
    this.gewaehltesGremiumAnschriftOrt = gewaehltesGremiumAnschriftOrt;
  }

  public String getGewaehltesGremiumAnschriftPlz() {
    return gewaehltesGremiumAnschriftPlz;
  }

  public void setGewaehltesGremiumAnschriftPlz(String gewaehltesGremiumAnschriftPlz) {
    this.gewaehltesGremiumAnschriftPlz = NlZipProperty.formatZip(gewaehltesGremiumAnschriftPlz);
  }

  public Anschrift getWahlausschusssitzungAnschrift() {
    return createAnschrift(getWahlausschusssitzungAnschriftStrasseHausnummer(), getWahlausschusssitzungAnschriftPlz(), getWahlausschusssitzungAnschriftOrt());
  }

  public String getWahlausschusssitzungAnschriftStrasseHausnummer() {
    return wahlausschusssitzungAnschriftStrasseHausnummer;
  }

  public void setWahlausschusssitzungAnschriftStrasseHausnummer(String wahlausschusssitzungAnschriftStrasseHausnummer) {
    this.wahlausschusssitzungAnschriftStrasseHausnummer = wahlausschusssitzungAnschriftStrasseHausnummer;
  }

  public String getWahlausschusssitzungAnschriftOrt() {
    return wahlausschusssitzungAnschriftOrt;
  }

  public void setWahlausschusssitzungAnschriftOrt(String wahlausschusssitzungAnschriftOrt) {
    this.wahlausschusssitzungAnschriftOrt = wahlausschusssitzungAnschriftOrt;
  }

  public String getWahlausschusssitzungAnschriftPlz() {
    return wahlausschusssitzungAnschriftPlz;
  }

  public void setWahlausschusssitzungAnschriftPlz(String wahlausschusssitzungAnschriftPlz) {
    this.wahlausschusssitzungAnschriftPlz = NlZipProperty.formatZip(wahlausschusssitzungAnschriftPlz);
  }

  public Date getWahlausschusssitzungBeginn() {
    return wahlausschusssitzungBeginn;
  }

  public void setWahlausschusssitzungBeginn(Date wahlausschusssitzungBeginn) {
    this.wahlausschusssitzungBeginn = wahlausschusssitzungBeginn;
  }

  public Date getWahlausschusssitzungEnde() {
    return wahlausschusssitzungEnde;
  }

  public void setWahlausschusssitzungEnde(Date wahlausschusssitzungEnde) {
    this.wahlausschusssitzungEnde = wahlausschusssitzungEnde;
  }

  public String getWahlausschusssitzungEinwaende() {
    return wahlausschusssitzungEinwaende;
  }

  public void setWahlausschusssitzungEinwaende(String wahlausschusssitzungEinwaende) {
    this.wahlausschusssitzungEinwaende = wahlausschusssitzungEinwaende;
  }

  public String getWahlausschusssitzungEinwaendeBemerkungen() {
    return wahlausschusssitzungEinwaendeBemerkungen;
  }

  public void setWahlausschusssitzungEinwaendeBemerkungen(String wahlausschusssitzungEinwaendeBemerkungen) {
    this.wahlausschusssitzungEinwaendeBemerkungen = wahlausschusssitzungEinwaendeBemerkungen;
  }

  public String getWahlausschusssitzungUnterzeichner1Name() {
    return wahlausschusssitzungUnterzeichner1Name;
  }

  public void setWahlausschusssitzungUnterzeichner1Name(String wahlausschusssitzungUnterzeichner1Name) {
    this.wahlausschusssitzungUnterzeichner1Name = wahlausschusssitzungUnterzeichner1Name;
  }

  public String getWahlausschusssitzungUnterzeichner1Rolle() {
    return wahlausschusssitzungUnterzeichner1Rolle;
  }

  public void setWahlausschusssitzungUnterzeichner1Rolle(String wahlausschusssitzungUnterzeichner1Rolle) {
    this.wahlausschusssitzungUnterzeichner1Rolle = wahlausschusssitzungUnterzeichner1Rolle;
  }

  public String getWahlausschusssitzungUnterzeichner2Name() {
    return wahlausschusssitzungUnterzeichner2Name;
  }

  public void setWahlausschusssitzungUnterzeichner2Name(String wahlausschusssitzungUnterzeichner2Name) {
    this.wahlausschusssitzungUnterzeichner2Name = wahlausschusssitzungUnterzeichner2Name;
  }

  public String getWahlausschusssitzungUnterzeichner2Rolle() {
    return wahlausschusssitzungUnterzeichner2Rolle;
  }

  public void setWahlausschusssitzungUnterzeichner2Rolle(String wahlausschusssitzungUnterzeichner2Rolle) {
    this.wahlausschusssitzungUnterzeichner2Rolle = wahlausschusssitzungUnterzeichner2Rolle;
  }

  public Date getFristZuletztGesetztBeginn() {
    return fristZuletztGesetztBeginn;
  }

  public void setFristZuletztGesetztBeginn(Date fristZuletztGesetztBeginn) {
    this.fristZuletztGesetztBeginn = fristZuletztGesetztBeginn;
  }

  public Date getFristZuletztGesetztEnde() {
    return fristZuletztGesetztEnde;
  }

  public void setFristZuletztGesetztEnde(Date fristZuletztGesetztEnde) {
    this.fristZuletztGesetztEnde = fristZuletztGesetztEnde;
  }

  public Date getWahlvorschlagEinreichungAbgabefrist() {
    return wahlvorschlagEinreichungAbgabefrist;
  }

  public void setWahlvorschlagEinreichungAbgabefrist(Date wahlvorschlagEinreichungAbgabefrist) {
    this.wahlvorschlagEinreichungAbgabefrist = wahlvorschlagEinreichungAbgabefrist;
  }

  public Anschrift getWahlvorschlagEinreichungAnschrift() {
    return createAnschrift("", "", getWahlvorschlagEinreichungAnschriftOrt());
  }

  public String getWahlvorschlagEinreichungAnschriftOrt() {
    return wahlvorschlagEinreichungAnschriftOrt;
  }

  public void setWahlvorschlagEinreichungAnschriftOrt(String wahlvorschlagEinreichungAnschriftOrt) {
    this.wahlvorschlagEinreichungAnschriftOrt = wahlvorschlagEinreichungAnschriftOrt;
  }

  public String getWahlvorschlagEinreichungUnterzeichner1Name() {
    return wahlvorschlagEinreichungUnterzeichner1Name;
  }

  public void setWahlvorschlagEinreichungUnterzeichner1Name(String wahlvorschlagEinreichungUnterzeichner1Name) {
    this.wahlvorschlagEinreichungUnterzeichner1Name = wahlvorschlagEinreichungUnterzeichner1Name;
  }

  public Date getWahlvorschlagVeroeffentlichungBeginn() {
    return wahlvorschlagVeroeffentlichungBeginn;
  }

  public void setWahlvorschlagVeroeffentlichungBeginn(Date wahlvorschlagVeroeffentlichungBeginn) {
    this.wahlvorschlagVeroeffentlichungBeginn = wahlvorschlagVeroeffentlichungBeginn;
  }

  public Anschrift getWahlvorschlagVeroeffentlichungAnschrift() {
    return createAnschrift("", "", getWahlvorschlagVeroeffentlichungAnschriftOrt());
  }

  public String getWahlvorschlagVeroeffentlichungAnschriftOrt() {
    return wahlvorschlagVeroeffentlichungAnschriftOrt;
  }

  public void setWahlvorschlagVeroeffentlichungAnschriftOrt(String wahlvorschlagVeroeffentlichungAnschriftOrt) {
    this.wahlvorschlagVeroeffentlichungAnschriftOrt = wahlvorschlagVeroeffentlichungAnschriftOrt;
  }

  public String getWahlvorschlagVeroeffentlichungUnterzeichner1Name() {
    return wahlvorschlagVeroeffentlichungUnterzeichner1Name;
  }

  public void setWahlvorschlagVeroeffentlichungUnterzeichner1Name(String wahlvorschlagVeroeffentlichungUnterzeichner1Name) {
    this.wahlvorschlagVeroeffentlichungUnterzeichner1Name = wahlvorschlagVeroeffentlichungUnterzeichner1Name;
  }

  public StimmzettelFormatterKandidaturFormatDarstellung getKandidaturFormatDarstellung() {
    return ErgebnisExchangeContext.KANDIDATUR_FORMAT_DARSTELLUNG_NOT_CONFIGURED;
  }

  public void copyFrom(Wahl wahl, AbstractWahlParameterLoader wahlParameterLoader) {
    if (wahl != null && wahlParameterLoader != null) {
      this.wahlbehoerdeWahlleiterName = WAHLBEHOERRDE_WAHLLEITER_NAME.getStringValue(wahl, wahlParameterLoader);

      this.wahlbehoerdeAnschriftStrasseHausnummer = WAHLBEHOERDE_ANSCHRIFT_STRASSE_HAUSNUMMER.getStringValue(wahl, wahlParameterLoader);
      this.wahlbehoerdeAnschriftOrt = WAHLBEHOERDE_ANSCHRIFT_ORT.getStringValue(wahl, wahlParameterLoader);
      this.wahlbehoerdeAnschriftPlz = NlZipProperty.formatZip(WAHLBEHOERDE_ANSCHRIFT_PLZ.getStringValue(wahl, wahlParameterLoader));

      this.gewaehltesGremiumAnschriftStrasseHausnummer = GEWAEHLTES_GREMIUM_ANSCHRIFT_STRASSE_HAUSNUMMER.getStringValue(wahl, wahlParameterLoader);
      this.gewaehltesGremiumAnschriftOrt = GEWAEHLTES_GREMIUM_ANSCHRIFT_ORT.getStringValue(wahl, wahlParameterLoader);
      this.gewaehltesGremiumAnschriftPlz = NlZipProperty.formatZip(GEWAEHLTES_GREMIUM_ANSCHRIFT_PLZ.getStringValue(wahl, wahlParameterLoader));

      this.wahlausschusssitzungAnschriftStrasseHausnummer = WAHLAUSSCHUSSSITZUNG_ANSCHRIFT_STRASSE_HAUSNUMMER.getStringValue(wahl, wahlParameterLoader);
      this.wahlausschusssitzungAnschriftOrt = WAHLAUSSCHUSSSITZUNG_ANSCHRIFT_ORT.getStringValue(wahl, wahlParameterLoader);
      this.wahlausschusssitzungAnschriftPlz = NlZipProperty.formatZip(WAHLAUSSCHUSSSITZUNG_ANSCHRIFT_PLZ.getStringValue(wahl, wahlParameterLoader));
      this.wahlausschusssitzungBeginn = WAHLAUSSCHUSSSITZUNG_BEGINN.getDateValue(wahl, wahlParameterLoader);
      this.wahlausschusssitzungEnde = WAHLAUSSCHUSSSITZUNG_ENDE.getDateValue(wahl, wahlParameterLoader);
      this.wahlausschusssitzungEinwaende = WAHLAUSSCHUSSSITZUNG_EINWAENDE.getStringValue(wahl, wahlParameterLoader);
      this.wahlausschusssitzungEinwaendeBemerkungen = WAHLAUSSCHUSSSITZUNG_EINWAENDE_BEMERKUNGEN.getStringValue(wahl, wahlParameterLoader);

      this.wahlausschusssitzungUnterzeichner1Name = WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER_1_NAME.getStringValue(wahl, wahlParameterLoader);
      this.wahlausschusssitzungUnterzeichner1Rolle = WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER_1_ROLLE.getStringValue(wahl, wahlParameterLoader);
      this.wahlausschusssitzungUnterzeichner2Name = WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER_2_NAME.getStringValue(wahl, wahlParameterLoader);
      this.wahlausschusssitzungUnterzeichner2Rolle = WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER_2_ROLLE.getStringValue(wahl, wahlParameterLoader);

      this.fristZuletztGesetztBeginn = FRIST_ZULETZT_GESETZT_BEGINN.getDateValue(wahl, wahlParameterLoader);
      this.fristZuletztGesetztEnde = FRIST_ZULETZT_GESETZT_ENDE.getDateValue(wahl, wahlParameterLoader);

      this.wahlvorschlagEinreichungAbgabefrist = WAHLVORSCHLAG_EINREICHUNG_ABGABEFRIST.getDateValue(wahl, wahlParameterLoader);
      this.wahlvorschlagEinreichungAnschriftOrt = WAHLVORSCHLAG_EINREICHUNG_ANSCHRIFT_ORT.getStringValue(wahl, wahlParameterLoader);
      this.wahlvorschlagEinreichungUnterzeichner1Name = WAHLVORSCHLAG_EINREICHUNG_UNTERZEICHNER_1_NAME.getStringValue(wahl, wahlParameterLoader);

      this.wahlvorschlagVeroeffentlichungBeginn = WAHLVORSCHLAG_VEROEFFENTLICHUNG_BEGINN.getDateValue(wahl, wahlParameterLoader);
      this.wahlvorschlagVeroeffentlichungAnschriftOrt = WAHLVORSCHLAG_VEROEFFENTLICHUNG_ANSCHRIFT_ORT.getStringValue(wahl, wahlParameterLoader);
      this.wahlvorschlagVeroeffentlichungUnterzeichner1Name = WAHLVORSCHLAG_VEROEFFENTLICHUNG_UNTERZEICHNER_1_NAME.getStringValue(wahl, wahlParameterLoader);
    }
  }

  public void copyTo(Wahl wahl, AbstractWahlParameterLoader wahlParameterLoader) {
    if (wahl != null) {
      WAHLBEHOERRDE_WAHLLEITER_NAME.setStringValue(wahl, wahlParameterLoader, this.wahlbehoerdeWahlleiterName);

      WAHLBEHOERDE_ANSCHRIFT_STRASSE_HAUSNUMMER.setStringValue(wahl, wahlParameterLoader, this.wahlbehoerdeAnschriftStrasseHausnummer);
      WAHLBEHOERDE_ANSCHRIFT_ORT.setStringValue(wahl, wahlParameterLoader, this.wahlbehoerdeAnschriftOrt);
      WAHLBEHOERDE_ANSCHRIFT_PLZ.setStringValue(wahl, wahlParameterLoader, this.wahlbehoerdeAnschriftPlz);

      GEWAEHLTES_GREMIUM_ANSCHRIFT_STRASSE_HAUSNUMMER.setStringValue(wahl, wahlParameterLoader, this.gewaehltesGremiumAnschriftStrasseHausnummer);
      GEWAEHLTES_GREMIUM_ANSCHRIFT_ORT.setStringValue(wahl, wahlParameterLoader, this.gewaehltesGremiumAnschriftOrt);
      GEWAEHLTES_GREMIUM_ANSCHRIFT_PLZ.setStringValue(wahl, wahlParameterLoader, this.gewaehltesGremiumAnschriftPlz);

      WAHLAUSSCHUSSSITZUNG_ANSCHRIFT_STRASSE_HAUSNUMMER.setStringValue(wahl, wahlParameterLoader, this.wahlausschusssitzungAnschriftStrasseHausnummer);
      WAHLAUSSCHUSSSITZUNG_ANSCHRIFT_ORT.setStringValue(wahl, wahlParameterLoader, this.wahlausschusssitzungAnschriftOrt);
      WAHLAUSSCHUSSSITZUNG_ANSCHRIFT_PLZ.setStringValue(wahl, wahlParameterLoader, this.wahlausschusssitzungAnschriftPlz);
      WAHLAUSSCHUSSSITZUNG_BEGINN.setDateValue(wahl, wahlParameterLoader, this.wahlausschusssitzungBeginn);
      WAHLAUSSCHUSSSITZUNG_ENDE.setDateValue(wahl, wahlParameterLoader, this.wahlausschusssitzungEnde);
      WAHLAUSSCHUSSSITZUNG_EINWAENDE.setStringValue(wahl, wahlParameterLoader, this.wahlausschusssitzungEinwaende);
      WAHLAUSSCHUSSSITZUNG_EINWAENDE_BEMERKUNGEN.setStringValue(wahl, wahlParameterLoader, this.wahlausschusssitzungEinwaendeBemerkungen);

      WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER_1_NAME.setStringValue(wahl, wahlParameterLoader, this.wahlausschusssitzungUnterzeichner1Name);
      WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER_1_ROLLE.setStringValue(wahl, wahlParameterLoader, this.wahlausschusssitzungUnterzeichner1Rolle);
      WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER_2_NAME.setStringValue(wahl, wahlParameterLoader, this.wahlausschusssitzungUnterzeichner2Name);
      WAHLAUSSCHUSSSITZUNG_UNTERZEICHNER_2_ROLLE.setStringValue(wahl, wahlParameterLoader, this.wahlausschusssitzungUnterzeichner2Rolle);

      FRIST_ZULETZT_GESETZT_BEGINN.setDateValue(wahl, wahlParameterLoader, this.fristZuletztGesetztBeginn);
      FRIST_ZULETZT_GESETZT_ENDE.setDateValue(wahl, wahlParameterLoader, this.fristZuletztGesetztEnde);

      WAHLVORSCHLAG_EINREICHUNG_ABGABEFRIST.setDateValue(wahl, wahlParameterLoader, this.wahlvorschlagEinreichungAbgabefrist);
      WAHLVORSCHLAG_EINREICHUNG_ANSCHRIFT_ORT.setStringValue(wahl, wahlParameterLoader, this.wahlvorschlagEinreichungAnschriftOrt);
      WAHLVORSCHLAG_EINREICHUNG_UNTERZEICHNER_1_NAME.setStringValue(wahl, wahlParameterLoader, this.wahlvorschlagEinreichungUnterzeichner1Name);

      WAHLVORSCHLAG_VEROEFFENTLICHUNG_BEGINN.setDateValue(wahl, wahlParameterLoader, this.wahlvorschlagVeroeffentlichungBeginn);
      WAHLVORSCHLAG_VEROEFFENTLICHUNG_ANSCHRIFT_ORT.setStringValue(wahl, wahlParameterLoader, this.wahlvorschlagVeroeffentlichungAnschriftOrt);
      WAHLVORSCHLAG_VEROEFFENTLICHUNG_UNTERZEICHNER_1_NAME.setStringValue(wahl, wahlParameterLoader, this.wahlvorschlagVeroeffentlichungUnterzeichner1Name);
    }
  }

  private Anschrift createAnschrift(String strasseHausnummer, String plz, String ort) {
    Anschrift anschrift = new Anschrift(EmptyCustomData.INSTANCE);
    anschrift.setAnschriftArt(AnschriftArt.ERREICHBARKEITSANSCHRIFT);
    anschrift.setStrasse(strasseHausnummer);
    anschrift.setPlz(plz);
    anschrift.setOrt(ort);

    return anschrift;
  }
}
