
package de.ivu.elect.presentation.kandidatur;

import javax.inject.Inject;
import javax.inject.Named;

import de.ivu.elect.business.ergebnis.entity.Gewaehlt;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.kandidatur.boundary.ErsatzkandidaturAufruecken;
import de.ivu.elect.business.kandidatur.entity.Ersatzkandidatur;
import de.ivu.elect.business.kandidatur.entity.Kandidatur;
import de.ivu.elect.business.kandidatur.entity.Listenkandidatur;
import de.ivu.elect.business.personenpruefung.boundary.PersonenKonfliktConversationSelect;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.security.UseCaseSecure;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.jee.faces.PreConditionCheck;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.redirect.Redirect;
import de.ivu.elect.presentation.gebietsbaum.GebietNummerFormatter;
import de.ivu.elect.presentation.hilfe.OnlineHilfeId;
import de.ivu.elect.presentation.kandidatur.form.ErsatzkandidaturViewFormBuilder;

@OnlineHilfeId(value = "260", mehrfachVergebenOk = true)
@Named(ErsatzkandidaturEditView.COMPONENT_NAME)
public class ErsatzkandidaturEditView extends AbstractErsatzkandidaturEditView {

  private static final long serialVersionUID = 1L;

  @Inject
  protected transient ErsatzkandidaturAufruecken ersatzkandidaturAufruecken;

  @Inject
  protected transient ErsatzkandidaturViewFormBuilder ersatzkandidaturViewFormBuilder;

  @Inject
  protected transient GebietNummerFormatter gebietNummerFormatter;

  @Inject
  protected transient PersonenKonfliktConversationSelect personenKonfliktConversationSelect;

  // parentViewId muss aufgelöst werden bevor ConversationStore geschlossen wird
  private String parentViewIdCache;

  public ErsatzkandidaturEditView() {
    super();
  }

  @Override
  @PreConditionCheck
  public String checkPreCondition() {
    super.checkPreCondition();

    if (isErsatzkandidaturSelected()) {
      return null;
    }

    return cancel();
  }

  @Override
  protected boolean isGebietBearbeitenRechtPruefen() {
    return true;
  }

  private boolean isErsatzkandidaturSelected() {
    return isEntitySet();
  }

  private boolean isErsatzkandidaturForListenkandidatur() {
    return isErsatzkandidaturSelected() && getWahlvorschlagKandidatur().isListenkandidatur();
  }

  private boolean isErsatzkandidaturForDirektkandidatur() {
    return isErsatzkandidaturSelected() && getWahlvorschlagKandidatur().isDirektkandidatur();
  }

  private Kandidatur getWahlvorschlagKandidatur() {
    if (isErsatzkandidaturSelected()) {
      return getEntity().getWahlvorschlagKandidatur();
    }

    return null;
  }

  private Gebiet getGebiet() {
    return getEntity().getGebiet();
  }

  public String getErsatzkandidaturName() {
    if (isErsatzkandidaturSelected()) {
      return getEntity().getFamilienname();
    }

    return "";
  }

  public String getUebergeordneteKandidaturName() {
    if (isErsatzkandidaturSelected()) {
      return getUebergeordneteKandidatur().getFamilienname();
    }

    return "";
  }

  private Kandidatur getUebergeordneteKandidatur() {
    return getEntity().getUebergeordneteKandidatur();
  }

  public String getGebietName() {
    if (isErsatzkandidaturSelected()) {
      return gebietNummerFormatter.getNameMitNummer(getGebiet());
    }

    return "";
  }

  private Wahl getWahl() {
    return getGebiet().getWahl();
  }

  private void verifyCompleteErsatzkandidatur() {
    if (!getEntity().hasGewaehltVorperiode()) {
      getEntity().setGewaehltVorperiode(createGewaehltVorperiode());
    }
  }

  private Gewaehlt createGewaehltVorperiode() {
    return ersatzkandidaturViewFormBuilder.createGewaehltVorperiode(getWahl());
  }

  @Override
  public void addProperties(FormBuilder formBuilder, Ersatzkandidatur entity) {
    boolean readonly = false;

    verifyCompleteErsatzkandidatur();

    if (isErsatzkandidaturForListenkandidatur()) {
      addListenkandidaturProperties(formBuilder);
    }

    addKandidaturProperties(formBuilder, readonly);
    addGewaehltVorperiodeProperties(formBuilder, readonly);
  }

  protected void addListenkandidaturProperties(FormBuilder formBuilder) {
    ersatzkandidaturViewFormBuilder.addListenkandidaturProperties(formBuilder, (Listenkandidatur) getWahlvorschlagKandidatur());
  }

  protected void addKandidaturProperties(FormBuilder formBuilder, boolean readonly) {
    ersatzkandidaturViewFormBuilder.addKandidaturProperties(formBuilder, getEntity(), readonly);
  }

  protected void addGewaehltVorperiodeProperties(FormBuilder formBuilder, boolean readonly) {
    ersatzkandidaturViewFormBuilder.addGewaehltVorperiodeProperties(formBuilder, getEntity(), getEntity().getGewaehltVorperiode(), readonly);
  }

  @Override
  @Redirect
  @UseCaseSecure(UseCasePermission.ERSATZKANDIDATUR_EDIT)
  public String save() {
    // ELECT-2788: Schließe den Konflikt, da er evtl. gelöst wurde.
    personenKonfliktConversationSelect.clearEntity();

    Ersatzkandidatur ersatzkandidatur = getEntity();

    ersatzkandidaturViewFormBuilder.preSaveEntity(ersatzkandidatur);

    parentViewIdCache = resolveParentViewId();

    return super.save();
  }

  @Override
  public String cancel() {
    parentViewIdCache = resolveParentViewId();
    return super.cancel();
  }

  @Override
  @Redirect
  @UseCaseSecure(UseCasePermission.ERSATZKANDIDATUR_DELETE)
  public String delete() {
    parentViewIdCache = resolveParentViewId();

    return super.delete();
  }

  @Redirect
  @UseCaseSecure(UseCasePermission.ERSATZKANDIDATUR_EDIT)
  public String aufruecken() {
    String parentViewId = getParentViewId();

    Ersatzkandidatur ersatzkandidatur = getEntity();
    Kandidatur uebergeordneteKandidatur = ersatzkandidatur.getUebergeordneteKandidatur();

    // NOTE, dass die Aufteilung in zwei Schritte notwendig ist! Das Löschen der übergeordneten Kandidatur innerhalb der
    // ersten Transaktion (aufruecken) wird (auf bisher unerklärliche Weise) ignoriert.
    ersatzkandidaturAufruecken.aufruecken(ersatzkandidatur);
    ersatzkandidaturAufruecken.tryDelete(uebergeordneteKandidatur);

    getMessages().addInfoMessage("ersatzkandidatur.edit.action.aufruecken.success.message", entityMeta.getEinzahlMessage());

    conversationStore.close();

    return parentViewId;
  }

  @Override
  protected String getParentViewId() {
    if (parentViewIdCache != null) {
      return parentViewIdCache;
    }

    return resolveParentViewId();
  }

  protected String resolveParentViewId() {
    if (isErsatzkandidaturForListenkandidatur()) {
      return ListenkandidaturSearchView.VIEW_ID;
    }

    if (isErsatzkandidaturForDirektkandidatur()) {
      return DirektkandidaturSearchView.VIEW_ID;
    }

    return getStartViewId();
  }

  @Override
  protected FormBuilder createFormBuilder() {
    return new FormBuilder(formBuilderConfig);
  }
}
