
package de.ivu.elect.presentation.gebietsbaum.exchange;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

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

import de.ivu.elect.business.datei.entity.DateiImport;
import de.ivu.elect.business.exchange.control.AbstractImporter;
import de.ivu.elect.business.gebietsbaum.boundary.AnzahlWahlberechtigteImporter;
import de.ivu.elect.business.gebietsbaum.boundary.GebietExtendedDAO;
import de.ivu.elect.business.gebietsbaum.control.GebietByBreadthFirstComparator;
import de.ivu.elect.business.gebietsbaum.entity.AnzahlWahlberechtigteImportContext;
import de.ivu.elect.business.gebietsbaum.entity.AnzahlWahlberechtigteExchangeObjekt;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.GebietPK;
import de.ivu.elect.business.security.UseCasePermission;
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.dynamicform.LambdaBooleanProperty;
import de.ivu.elect.presentation.LambdaEntitySelectOneMenuProperty;
import de.ivu.elect.presentation.View;
import de.ivu.elect.presentation.exchange.AbstractImportBestaetigenView;
import de.ivu.elect.presentation.exchange.ImportDescription;
import de.ivu.elect.presentation.gebietsbaum.AnzahlWahlberechtigteErfassungState;
import de.ivu.elect.presentation.gebietsbaum.GebietNummerFormatter;

@Named(AnzahlWahlberechtigteImportBestaetigenView.COMPONENT_NAME)
@View(viewId = AnzahlWahlberechtigteImportBestaetigenView.VIEW_ID, useCase = UseCasePermission.ANZAHL_WAHLBERECHTIGTE_IMPORTIEREN)
public class AnzahlWahlberechtigteImportBestaetigenView extends AbstractImportBestaetigenView<AnzahlWahlberechtigteExchangeObjekt, AnzahlWahlberechtigteImportContext> {

  private static final long serialVersionUID = 1L;

  public static final String COMPONENT_NAME = "anzahlWahlberechtigteImportBestaetigenView";

  public static final String VIEW_ID = "/gebietsbaum/anzahl-wahlberechtigte-import-bestaetigen.xhtml";

  @Inject
  private transient AnzahlWahlberechtigteErfassungState anzahlWahlberechtigteErfassungState;

  @Inject
  private transient AnzahlWahlberechtigteImportDescription anzahlWahlberechtigteImportDescription;

  @Inject
  private transient AnzahlWahlberechtigteImporter anzahlWahlberechtigteImporter;

  @Inject
  private transient GebietNummerFormatter gebietNummerFormatter;

  @Inject
  private transient GebietExtendedDAO gebietExtendedDAO;

  private GebietPK uebergeordnetesGebietPK;

  private boolean erfassteGebietUeberschreiben;

  public AnzahlWahlberechtigteImportBestaetigenView() {
    super();
  }

  @Override
  @PreConditionCheck
  public String checkPreCondition() {
    if (anzahlWahlberechtigteErfassungState.isImportMoeglich(getSelectedWahl())) {
      return super.checkPreCondition();
    }

    return getStartViewId();
  }

  @Override
  protected ImportDescription getImportDescription() {
    return anzahlWahlberechtigteImportDescription;
  }

  @Override
  protected AbstractImporter<AnzahlWahlberechtigteExchangeObjekt, AnzahlWahlberechtigteImportContext, ?> getImporter() {
    return anzahlWahlberechtigteImporter;
  }

  @Override
  protected void addProperties(FormBuilder formBuilder, DateiImport dateiImport, AnzahlWahlberechtigteImportContext anzahlWahlberechtigteImportContext) {
    getImportReport(); // HINT: Import-Vorschau einmal erzeugen, um den Mapper zu befüllen

    super.addProperties(formBuilder, dateiImport, anzahlWahlberechtigteImportContext);
    List<Gebiet> values = bestimmeMoeglicheUebergeordneteGebiete(getSelectedWahl());
    if (!values.isEmpty()) {
      formBuilder.addProperty(new LambdaEntitySelectOneMenuProperty<>(values, this::setUebergeordnetesGebiet, this::getUebergeordnetesGebiet,
          gebietNummerFormatter::getDarstellung, "anzahl.wahlberechtigte.import.uebergeordnetes.gebiet", false, true));
    }

    formBuilder.addProperty(new LambdaBooleanProperty(getMessage("anzahl.wahlberechtigte.import.erfasste.gebiete.ueberschreiben"), false,
        this::setErfassteGebietUeberschreiben, this::isErfassteGebietUeberschreiben));

  }

  private List<Gebiet> bestimmeMoeglicheUebergeordneteGebiete(Wahl selectedWahl) {

    if (selectedWahl == null) {
      return Collections.emptyList();
    }

    return gebietExtendedDAO.findByWahl(selectedWahl).stream().map(Gebiet::getUebergeordnetesGebiet)
        .filter(Objects::nonNull).distinct().sorted(new GebietByBreadthFirstComparator()).collect(Collectors.toList());

  }

  @Nullable
  public Gebiet getUebergeordnetesGebiet() {
    if (uebergeordnetesGebietPK == null) {
      return null;
    }
    return gebietExtendedDAO.findByPrimaryKey(uebergeordnetesGebietPK);
  }

  public void setUebergeordnetesGebiet(Gebiet uebergeordnetesGebiet) {
    if (uebergeordnetesGebiet == null) {
      this.uebergeordnetesGebietPK = null;
    } else {
      this.uebergeordnetesGebietPK = uebergeordnetesGebiet.getPk();
    }
  }

  public boolean isErfassteGebietUeberschreiben() {
    return erfassteGebietUeberschreiben;
  }

  public void setErfassteGebietUeberschreiben(boolean erfassteGebietUeberschreiben) {
    this.erfassteGebietUeberschreiben = erfassteGebietUeberschreiben;
  }

  @Override
  protected AnzahlWahlberechtigteImportContext getContext() {
    return new AnzahlWahlberechtigteImportContext(getSelectedWahl(), getUebergeordnetesGebiet(), isErfassteGebietUeberschreiben());
  }

}
