
package de.ivu.elect.dokumente.kandidatur;

import static de.ivu.elect.jee.entity.EntityUtil.castTo;

import javax.annotation.Nullable;

import de.ivu.document.generator.template.annotations.Document;
import de.ivu.document.generator.template.annotations.DocumentSimpleField;
import de.ivu.elect.business.dokumente.entity.DokumentVorlageArt;
import de.ivu.elect.business.kandidatur.entity.Kandidatur;
import de.ivu.elect.business.kandidatur.entity.Listenkandidatur;
import de.ivu.elect.business.kandidatur.entity.ListenkandidaturStimmzettelPosition;
import de.ivu.elect.business.stimmzettel.entity.EntityAufStimmzettelDaten;
import de.ivu.elect.business.wahlvorschlag.entity.WahlvorschlagStimmzettelPosition;
import de.ivu.elect.dokumente.CoreElectContext;
import de.ivu.elect.dokumente.ParameterKey;
import de.ivu.elect.dokumente.wahlvorschlag.CoreWahlvorschlagsdatenDocument;

@Document(value = DokumentVorlageArt.KANDIDATUR_SUB_TEMPLATE, isSubTemplate = true)
public class CoreKandidaturDokument extends KandidaturDokument {

  private static final long serialVersionUID = 1L;

  public static final CoreKandidaturDokument EMPTY_OBJECT = new CoreKandidaturDokument();

  @DocumentSimpleField("LaufendeNummer")
  public final Long laufendeNummer;

  @DocumentSimpleField("IstListenkandidatur")
  public final boolean listenkandidatur;

  @DocumentSimpleField("IstDirektkandidatur")
  public final boolean direktkandidatur;

  @DocumentSimpleField("IstErsatzkandidatur")
  public final boolean ersatzkandidatur;

  /**
   * @deprecated
   * @see CoreKandidaturDokument#listenkandidaturPositionStimmzettel
   */
  @Deprecated
  @DocumentSimpleField("Listenposition")
  public final Long listenposition;

  @Nullable
  @DocumentSimpleField("ListenkandidaturPositionStimmzettel")
  public final Long listenkandidaturPositionStimmzettel;

  @DocumentSimpleField("ListenkandidaturPositionStimmzettel-Formatiert")
  public final String listenkandidaturPositionStimmzettelFormatted;

  @DocumentSimpleField("ListenkandidaturKennzahlStimmzettel-Formatiert")
  public final String listenkandidaturKennzahlStimmzettelFormatted;

  /**
   * @deprecated
   * @see CoreKandidaturDokument#listenkandidaturPositionEingereicht
   */
  @Deprecated
  @DocumentSimpleField("ErfasstePosition")
  public final Long erfasstePosition;

  @Nullable
  @DocumentSimpleField("ListenkandidaturPositionEingereicht")
  public final Long listenkandidaturPositionEingereicht;

  @Nullable
  @DocumentSimpleField("ListenkandidaturAnzahlNennungen")
  public final Long listenkandidaturAnzahlNennungen;

  protected final WahlvorschlagStimmzettelPosition stimmzettelPositionWahlvorschlag;

  protected final ListenkandidaturStimmzettelPosition listenkandidaturStimmzettelPosition;

  protected CoreKandidaturDokument() {
    super();

    this.laufendeNummer = 0L;

    this.stimmzettelPositionWahlvorschlag = WahlvorschlagStimmzettelPosition.EMPTY;

    this.listenkandidaturStimmzettelPosition = ListenkandidaturStimmzettelPosition.EMPTY;
    this.listenkandidatur = false;

    this.listenkandidaturPositionStimmzettel = null;
    this.listenposition = this.listenkandidaturPositionStimmzettel;
    this.listenkandidaturPositionEingereicht = 0L;
    this.erfasstePosition = this.listenkandidaturPositionEingereicht;

    this.listenkandidaturPositionStimmzettelFormatted = "";
    this.listenkandidaturKennzahlStimmzettelFormatted = "";

    this.listenkandidaturAnzahlNennungen = null;

    this.direktkandidatur = false;

    this.ersatzkandidatur = false;
  }

  public CoreKandidaturDokument(CoreElectContext coreElectContext, CoreWahlvorschlagsdatenDocument wahlvorschlagsdatenDocument, KandidaturCoreDaten kandidaturCoreDaten, Kandidatur kandidatur,
      Long laufendeNummer) {
    super(coreElectContext, wahlvorschlagsdatenDocument, kandidaturCoreDaten, kandidatur);

    EntityAufStimmzettelDaten entityAufStimmzettelDaten = kandidaturCoreDaten.getEntityAufStimmzettelDaten();

    this.laufendeNummer = laufendeNummer;

    this.stimmzettelPositionWahlvorschlag = kandidatur.getWahlvorschlag().getStimmzettelPosition(entityAufStimmzettelDaten);

    if (kandidatur.isListenkandidatur()) {
      Listenkandidatur listenkandidaturEntity = castTo(kandidatur, Listenkandidatur.class);

      this.listenkandidaturStimmzettelPosition = listenkandidaturEntity.getStimmzettelPosition(entityAufStimmzettelDaten);
      this.listenkandidatur = true;

      this.listenkandidaturPositionStimmzettel = listenkandidaturStimmzettelPosition.getPosition();
      this.listenposition = this.listenkandidaturPositionStimmzettel;
      this.listenkandidaturPositionEingereicht = listenkandidaturEntity.getEingereichtePosition();
      this.erfasstePosition = this.listenkandidaturPositionEingereicht;

      this.listenkandidaturPositionStimmzettelFormatted = this.listenkandidaturStimmzettelPosition.formatPosition(this.stimmzettelPositionWahlvorschlag);
      this.listenkandidaturKennzahlStimmzettelFormatted = this.listenkandidaturStimmzettelPosition.formatKennzahl(this.stimmzettelPositionWahlvorschlag);

      this.listenkandidaturAnzahlNennungen = listenkandidaturEntity.getAnzahlNennungen();

      this.direktkandidatur = false;

      this.ersatzkandidatur = listenkandidaturEntity.isListenkandidaturMarkiertAlsErsatzkandidatur();
    } else if (kandidatur.isDirektkandidatur()) {
      this.listenkandidaturStimmzettelPosition = ListenkandidaturStimmzettelPosition.EMPTY;
      this.listenkandidatur = false;

      this.listenkandidaturPositionStimmzettel = null;
      this.listenposition = this.listenkandidaturPositionStimmzettel;
      this.listenkandidaturPositionEingereicht = null;
      this.erfasstePosition = this.listenkandidaturPositionEingereicht;

      this.listenkandidaturPositionStimmzettelFormatted = "";
      this.listenkandidaturKennzahlStimmzettelFormatted = "";

      this.listenkandidaturAnzahlNennungen = null;

      this.direktkandidatur = true;

      this.ersatzkandidatur = false;
    } else if (kandidatur.isErsatzkandidatur()) {
      this.listenkandidaturStimmzettelPosition = ListenkandidaturStimmzettelPosition.EMPTY;
      this.listenkandidatur = false;

      this.listenkandidaturPositionStimmzettel = null;
      this.listenposition = this.listenkandidaturPositionStimmzettel;
      this.listenkandidaturPositionEingereicht = null;
      this.erfasstePosition = this.listenkandidaturPositionEingereicht;

      this.listenkandidaturPositionStimmzettelFormatted = "";
      this.listenkandidaturKennzahlStimmzettelFormatted = "";

      this.listenkandidaturAnzahlNennungen = null;

      this.direktkandidatur = false;

      this.ersatzkandidatur = true;
    } else {
      throw new IllegalStateException("Unbekannte KandidaturArt:" + kandidatur);
    }
  }

  public static CoreKandidaturDokument lookupOrCreate(CoreElectContext coreElectContext, CoreWahlvorschlagsdatenDocument wahlvorschlagsdatenDocument, KandidaturCoreDaten kandidaturCoreDaten,
      Kandidatur kandidatur, Long laufendeNummer) {
    ParameterKey paremeterKey = new ParameterKey(kandidatur, laufendeNummer);

    CoreKandidaturDokument result = coreElectContext.lookupCachedDokument(CoreKandidaturDokument.class, paremeterKey);

    if (result == null) {
      result = new CoreKandidaturDokument(coreElectContext, wahlvorschlagsdatenDocument, kandidaturCoreDaten, kandidatur, laufendeNummer);

      coreElectContext.cacheDokument(CoreKandidaturDokument.class, paremeterKey, result);
    }

    return result;
  }

  @Override
  public boolean isEmptyObject() {
    return this == EMPTY_OBJECT;
  }
}
