
package de.ivu.elect.presentation.gebietsbaum;

import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.validation.constraints.NotNull;

import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.stimmeingabe.boundary.LetzterEingangLoader;
import de.ivu.elect.business.wahl.boundary.UmgangAWerteKonfiguration;
import de.ivu.elect.business.wahl.entity.UmgangHinterlegteAWerte;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.WahlParameterExtendedLoader;
import de.ivu.elect.business.wahl.entity.WahlParameterWerte;
import de.ivu.elect.presentation.replikation.ReplikationPresentationStatus;


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

public class AnzahlWahlberechtigteErfassungState {

  @Inject
  private transient ReplikationPresentationStatus replikationPresentationStatus;

  @Inject
  private transient UmgangAWerteKonfiguration umgangAWerteKonfiguration;

  @Inject
  private transient WahlParameterExtendedLoader wahlParameterExtendedLoader;

  @Inject
  private transient LetzterEingangLoader letzterEingangLoader;

  public AnzahlWahlberechtigteErfassungState() {
    super();
  }

  public boolean isImportMoeglich(@Nullable Wahl wahl) {
    return wahl != null && isErfassungMoeglich(wahl) && !isErfassungGesperrt(wahl);
  }

  public boolean isErfassungMoeglich(@Nullable Wahl wahl) {
    return wahl != null && umgangAWerteKonfiguration.isAnyAnzahlWahlberechtigteAmGebietErfassbar(wahl);
  }

  public boolean isErfassungMoeglich(@Nullable Gebiet gebiet) {
    return gebiet != null && gebiet.isInstanceOf(Wahldurchfuehrungsgebiet.class) && isErfassungMoeglich(castTo(gebiet, Wahldurchfuehrungsgebiet.class));
  }

  private boolean isErfassungMoeglich(@Nullable Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet) {
    return wahldurchfuehrungsgebiet != null && isErfassungMoeglich(wahldurchfuehrungsgebiet.getWahl())
            && isErfassungMoeglichKonfiguriert(wahldurchfuehrungsgebiet);
  }

  private boolean isErfassungMoeglichKonfiguriert(@NotNull Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet) {
    return getUmgangHinterlegteAWerte(wahldurchfuehrungsgebiet).isErfassungMoeglich(wahldurchfuehrungsgebiet::isBriefwahlgebiet, () -> wahldurchfuehrungsgebiet.isPersistent() || hasGebietsartErfassungsgebiet(wahldurchfuehrungsgebiet));
  }

  private UmgangHinterlegteAWerte getUmgangHinterlegteAWerte(@NotNull Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet) {
    return wahlParameterExtendedLoader.resolveEnumValue(wahldurchfuehrungsgebiet.getWahl(), WahlParameterWerte.UMGANG_AWERTE_HINTERLEGT, UmgangHinterlegteAWerte.class);
  }


  public boolean isErfassungGesperrt(@Nullable Wahl wahl) {
    return wahl == null || isSlave();
  }

  public boolean isErfassungGesperrt(@Nullable Gebiet gebiet) {
    if (gebiet == null || !gebiet.isInstanceOf(Wahldurchfuehrungsgebiet.class)) {
      return true;
    }
    Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = gebiet.castTo(Wahldurchfuehrungsgebiet.class).getEntity();

    return getUmgangHinterlegteAWerte(wahldurchfuehrungsgebiet).isErfassungGesperrt(
        () -> isErfassungGesperrtByGebietsart(wahldurchfuehrungsgebiet),
        () -> isErfassungGesperrtByErgebniseingang(wahldurchfuehrungsgebiet));
  }

  public boolean isErfassungGesperrtLautGebietsart(@Nullable Gebiet gebiet) {
    if (gebiet == null || !gebiet.isInstanceOf(Wahldurchfuehrungsgebiet.class)) {
      return true;
    }
    Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = gebiet.castTo(Wahldurchfuehrungsgebiet.class).getEntity();

    return getUmgangHinterlegteAWerte(wahldurchfuehrungsgebiet).isErfassungGesperrt(
        () -> isErfassungGesperrtByGebietsart(wahldurchfuehrungsgebiet),
        () -> false);
  }

  public boolean isErfassungGesperrtByGebietsart(Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet) {
    return isErfassungGesperrt(wahldurchfuehrungsgebiet.getWahl()) || !wahldurchfuehrungsgebiet.isErfassungsgebietLautGebietsart();
  }

  public boolean isErfassungGesperrtByErgebniseingang(Gebiet gebiet) {
    return gebiet == null || !gebiet.isInstanceOf(Wahldurchfuehrungsgebiet.class) || isErfassungGesperrtByErgebniseingang(
        gebiet.castTo(Wahldurchfuehrungsgebiet.class).getEntity());
  }

  private boolean isErfassungGesperrtByErgebniseingang(Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet) {
    return isErfassungMoeglich(wahldurchfuehrungsgebiet) && (letzterEingangLoader.hasAnyErgebniseingang(wahldurchfuehrungsgebiet.getWahl().getPk(),
        wahldurchfuehrungsgebiet.getPk())) || (wahldurchfuehrungsgebiet.getErfasstIn() != null && isErfassungGesperrtByErgebniseingang(
        wahldurchfuehrungsgebiet.getErfasstIn()));
  }

  // WASDE-1153
  private boolean isSlave() {
    return replikationPresentationStatus.isSlave();
  }

  private boolean hasGebietsartErfassungsgebiet(Gebiet gebiet) {
    return gebiet != null && gebiet.getGebietsart() != null && !gebiet.getGebietsart().getBezirksart().isKeine();
  }

  public boolean isAnzahlWahlberechtigeOhneWahlscheinReadOnly(Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet) {
    if (wahldurchfuehrungsgebiet == null || !wahldurchfuehrungsgebiet.isPersistent()) {
      return false;
    }
    return getUmgangHinterlegteAWerte(wahldurchfuehrungsgebiet).isAnzahlWahlberechtigeOhneWahlscheinReadOnly(wahldurchfuehrungsgebiet::isBriefwahlgebiet);
  }
}
