
package de.ivu.elect.presentation.stimmeingabe.status;

import java.util.List;

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

import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.stimmeingabe.boundary.AbstractStimmeingabefehlerDAO;
import de.ivu.elect.business.stimmeingabe.boundary.ErgebniseingangKonfiguration;
import de.ivu.elect.business.stimmeingabe.boundary.StimmeingabefehlerExtendedDAO;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingabestatus;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingabestufe;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingang;
import de.ivu.elect.business.stimmeingabe.entity.Ergebniseingangsart;
import de.ivu.elect.presentation.gebietsbaum.status.ErgebniseingangStatusEntry;
import de.ivu.elect.presentation.status.AbstractStatusEntryFactory;
import de.ivu.elect.presentation.stimmeingabe.StimmeingabeSecurity;

public class ErgebniseingangStatusEntryFactory extends AbstractStatusEntryFactory {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient StimmeingabeSecurity stimmeingabeSecurity;

  @Inject
  private transient StimmeingabefehlerExtendedDAO stimmeingabefehlerExtendedDAO;

  @Inject
  private transient ErgebniseingangKonfiguration ergebniseingangKonfiguration;

  @Inject
  private transient ErgebniseingangAufVollstaendigkeitPruefenSchalter ergebniseingangAufVollstaendigkeitPruefenSchalter;

  public ErgebniseingangStatusEntryFactory() {
    super();
  }

  public ErgebniseingangStatusEntry create(Wahldurchfuehrungsgebiet gebiet, @Nullable Ergebniseingang letzterErgebniseingang, Ergebniseingangsart ergebniseingangsart) {
    Ergebniseingabestufe ergebniseingabestufe = ergebniseingangKonfiguration.getErgebniseingabestufeInitial(gebiet.getWahldurchfuehrung());

    String tooltipMessageKey;
    String tooltipExtraText = "";

    GebietErfassungsstatus gebietErfassungsstatus;
    if (letzterErgebniseingang == null) {
      gebietErfassungsstatus = GebietErfassungsstatus.fromErgebniseingang(null, isErgebniseingangAufVollstaendigkeitPruefen(), gebiet, ergebniseingangsart);
      if (gebietErfassungsstatus.isAusbleibend()) {
        tooltipMessageKey = "ergebniseingang.status.tooltip.ausbleibend";
      } else {
        tooltipMessageKey = "ergebniseingang.status.tooltip.kein.eingang";
      }

      if (gebiet.getErfasstIn() != null) {
        tooltipExtraText = getMessage("ergebniseingang.status.tooltip.erfasst.in", getGebietNummerFormatter().getDarstellung(gebiet.getErfasstIn()));
      }

    } else {

      ergebniseingabestufe = letzterErgebniseingang.getErgebniseingabestufe();

      gebietErfassungsstatus = letzterErgebniseingang.getErgebniseingangsfehlerstatus().getGebietErfassungsstatus();
      tooltipMessageKey = "Ergebniseingangsfehlerstatus.tooltip." + letzterErgebniseingang.getErgebniseingangsfehlerstatus().name();

      if (letzterErgebniseingang.isFiktiv() && !gebietErfassungsstatus.isFehlerVorhanden() && hasPermissionToSeeErgebniseingangIstFiktiv()) {
        gebietErfassungsstatus = GebietErfassungsstatus.FIKTIV;
        tooltipMessageKey = "ergebniseingang.status.tooltip.fiktiver.eingang";
      }

      if (GebietErfassungsstatus.GUELTIG.equals(gebietErfassungsstatus) && isErgebniseingangAufVollstaendigkeitPruefen() && isUnvollstaendig(
          letzterErgebniseingang, gebiet, ergebniseingangsart)) {
        gebietErfassungsstatus = GebietErfassungsstatus.UNVOLLSTAENDIG;
        tooltipMessageKey = "ergebniseingang.status.tooltip.unvollstaendiger.eingang";
      }

      // ELECT-3618 - Erfassungsfehler auf Statusseite anzeigen

      if (!letzterErgebniseingang.isGueltig()) {
        tooltipExtraText = formatFehlerbeschreibungenTooltip(letzterErgebniseingang, stimmeingabefehlerExtendedDAO);
      }

      if (tooltipExtraText.length() > 0) {
        tooltipExtraText += TOOLTIP_LINE_SEPARATOR + TOOLTIP_LINE_SEPARATOR;
      }

      tooltipExtraText += getMessage("ergebniseingang.status.tooltip.zeitstempel.letztereingang", formatDateTime(letzterErgebniseingang.getZeitstempel()));
    }

    ErgebniseingangStatusEntry gebietsbaumStatusEntry = new ErgebniseingangStatusEntry(gebiet, getGebietNummerFormatter(),
        new GebietErfassungsstatusInErgebniseingabestufe(ergebniseingabestufe, gebietErfassungsstatus), ergebniseingangsart.korrespondierendeErgebnisart());

    String tooltipInformation = formatTooltipGebietDarstellung(gebiet);

    if (gebiet.isErfassungsgebietLautGebietsart()) {
      Ergebniseingabestatus ergebniseingabestatus = gebiet.getErgebniseingabestatus(ergebniseingangsart.korrespondierendeErgebnisart());
      tooltipInformation += TOOLTIP_LINE_SEPARATOR + getMessage(ergebniseingabestatus);
    }

    tooltipInformation += TOOLTIP_LINE_SEPARATOR + TOOLTIP_LINE_SEPARATOR + getMessage(tooltipMessageKey);

    if (tooltipExtraText.length() > 0) {
      tooltipInformation += TOOLTIP_LINE_SEPARATOR + TOOLTIP_LINE_SEPARATOR + tooltipExtraText;
    }

    gebietsbaumStatusEntry.addTooltipInformation(tooltipInformation);

    return gebietsbaumStatusEntry;
  }

  public static String formatFehlerbeschreibungenTooltip(Ergebniseingang letzterErgebniseingang, AbstractStimmeingabefehlerDAO stimmeingabefehlerDAO) {
    return String.join(TOOLTIP_LINE_SEPARATOR + TOOLTIP_LINE_SEPARATOR, getFehlerbeschreibungen(letzterErgebniseingang, stimmeingabefehlerDAO));
  }

  public static List<String> getFehlerbeschreibungen(Ergebniseingang letzterErgebniseingang, AbstractStimmeingabefehlerDAO stimmeingabefehlerDAO) {
    return letzterErgebniseingang.getStimmeingabefehlerBeschreibungen(stimmeingabefehlerDAO);
  }

  private boolean isUnvollstaendig(Ergebniseingang letzterErgebniseingang, Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet,
                                   Ergebniseingangsart ergebniseingangsart) {
    return GebietErfassungsstatus.UNVOLLSTAENDIG.equals(GebietErfassungsstatus.fromErgebniseingang(letzterErgebniseingang,
        isErgebniseingangAufVollstaendigkeitPruefen(), wahldurchfuehrungsgebiet, ergebniseingangsart));
  }

  protected boolean isErgebniseingangAufVollstaendigkeitPruefen() {
    return ergebniseingangAufVollstaendigkeitPruefenSchalter.isErgebniseingangAufVollstaendigkeitPruefen();
  }

  protected boolean hasPermissionToSeeErgebniseingangIstFiktiv() {
    return stimmeingabeSecurity.hasPermissionLetzterErgebniseingangFiktivErkennen();
  }
}
