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

import java.util.Objects;
import java.util.Optional;

import javax.annotation.Nullable;
import javax.inject.Inject;

import de.ivu.elect.business.kandidatur.entity.Kandidatur;
import de.ivu.elect.business.wahlrechtspruefung.boundary.PruefkriteriumDAO;
import de.ivu.elect.business.wahlrechtspruefung.entity.AbstractPruefkriterium;
import de.ivu.elect.business.wahlrechtspruefung.entity.Pruefkriterium;
import de.ivu.elect.business.wahlrechtspruefung.entity.PruefkriteriumDaoContainer;
import de.ivu.elect.business.wahlrechtspruefung.entity.WahlrechtspruefStatus;
import de.ivu.elect.business.wahlrechtspruefung.entity.Wahlrechtspruefung;
import de.ivu.elect.business.wahlvorschlag.entity.Wahlvorschlag;

public class WahlrechtspruefungCreate extends AbstractWahlrechtspruefungCreate {

  @Inject
  private transient PruefkriteriumDAO pruefkriteriumDAO;

  @Inject
  private transient PruefkriteriumDaoContainer pruefkriteriumDaoContainer;

  public WahlrechtspruefungCreate() {
    super();
  }

  public void save(Pruefkriterium pruefkriterium, Object entitaetZuPruefen, @Nullable Kandidatur kandidatur) {
    Wahlrechtspruefung wahlrechtspruefung = new Wahlrechtspruefung();
    wahlrechtspruefung.setPruefkriterium(pruefkriterium);
    wahlrechtspruefung.setWahlrechtspruefStatus(getWahlrechtspruefStatusInitial(pruefkriterium));
    wahlrechtspruefung.setKandidatur(kandidatur);

    pruefkriterium.getPruefkriteriumBezug().setzeZuPruefendeEntitaet(wahlrechtspruefung, entitaetZuPruefen, pruefkriteriumDaoContainer);

    save(wahlrechtspruefung);
  }

  protected WahlrechtspruefStatus getWahlrechtspruefStatusInitial(Pruefkriterium pruefkriterium) {
    return pruefkriterium.getInitialerStatus();
  }

  @Override
  public void save(Wahlrechtspruefung wahlrechtspruefung) {
    // ELECT-10913, Wahlrechtsprüfungen nur einmalig (beim Import oder dem Anlegen eines Wahlvorschlages/einer Kandidatur) anlegen...
    if (isSkipPruefung(wahlrechtspruefung)) {
      super.save(wahlrechtspruefung);
    } else {
      Optional<Wahlrechtspruefung> existing = existsWahlrechtspruefung(attach(wahlrechtspruefung.getPruefkriterium()),
          attach(wahlrechtspruefung.getWahlvorschlag()), wahlrechtspruefung.getKandidatur());
      if (existing.isPresent()) {
        wahlrechtspruefung.copyEntityAttributesUsingSetter(existing.get()); // bestehende aktualisieren
      } else {
        super.save(wahlrechtspruefung);
      }
    }
  }

  private boolean isSkipPruefung(Wahlrechtspruefung wahlrechtspruefung) {
    if (wahlrechtspruefung.getKandidatur() != null) {
      return Boolean.TRUE.equals(wahlrechtspruefung.getKandidatur().getTransientContext().get(AbstractPruefkriterium.KEINE_EXISTENZPRUEFUNG_BEIM_ANLEGEN));
    }
    return Boolean.TRUE.equals(wahlrechtspruefung.getWahlvorschlag().getTransientContext().get(AbstractPruefkriterium.KEINE_EXISTENZPRUEFUNG_BEIM_ANLEGEN));
  }

  private Optional<Wahlrechtspruefung> existsWahlrechtspruefung(Pruefkriterium pruefkriterium, Wahlvorschlag wahlvorschlag, Kandidatur kandidatur) {
    if (wahlvorschlag != null) {
      return dao.findByWahlvorschlag(wahlvorschlag).stream()
          .filter(
              wahlrechtspruefung -> Objects.equals(wahlrechtspruefung.getPruefkriterium(), pruefkriterium) && Objects.equals(wahlrechtspruefung.getKandidatur(),
                  kandidatur)).findAny();
    }

    return Optional.empty();
  }

  private Pruefkriterium attach(Pruefkriterium pruefkriterium) {
    return pruefkriteriumDAO.attach(pruefkriterium);
  }

  private Wahlvorschlag attach(Wahlvorschlag wahlvorschlag) {
    return pruefkriteriumDaoContainer.getWahlvorschlagDAO().attach(wahlvorschlag);
  }
}
