
package de.ivu.elect.presentation.ergebniskonflikt;

import static java.util.stream.Collectors.toSet;

import java.util.Collection;
import java.util.List;
import java.util.Objects;

import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

import de.ivu.elect.business.ergebniskonflikt.entity.AbstractErgebnisKonfliktLosoptionenCustomData;
import de.ivu.elect.business.ergebniskonflikt.entity.ErgebnisKonflikt;
import de.ivu.elect.business.ergebniskonflikt.entity.ErgebnisKonfliktAnzahlZuLosenProperty;
import de.ivu.elect.business.ergebniskonflikt.entity.ErgebnisKonfliktLosoption;
import de.ivu.elect.business.ergebniskonflikt.entity.ErgebnisKonfliktLosoptionPickListProperty;
import de.ivu.elect.business.ergebniskonflikt.entity.ErgebnisKonfliktLosoptionSelectOneMenuProperty;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.dynamicform.PickListTargetSizeRangeValidator;
import de.ivu.elect.presentation.View;

@RequestScoped
@Named(ErgebnisKonfliktLosoptionenAuswaehlenView.COMPONENT_NAME)
@View(viewId = ErgebnisKonfliktLosoptionenAuswaehlenView.VIEW_ID, useCase = UseCasePermission.ERGEBNIS_KONFLIKT_EDIT)
public class ErgebnisKonfliktLosoptionenAuswaehlenView extends AbstractErgebnisKonfliktLoesenView<AbstractErgebnisKonfliktLosoptionenCustomData> {

  private static final long serialVersionUID = 1L;

  public static final String COMPONENT_NAME = "ergebnisKonfliktLosoptionenAuswaehlenView";

  public static final String VIEW_ID = AbstractErgebnisKonfliktLosoptionenCustomData.VIEW_ID;

  public ErgebnisKonfliktLosoptionenAuswaehlenView() {
    super();
  }

  @Override
  protected Collection<Gebiet> getErgebnisKonfliktGebiete() {
    return getLosoptionenVerfuegbar(getEntity()).stream().filter(ErgebnisKonfliktLosoption::hasGebiet).map(ErgebnisKonfliktLosoption::getGebiet).filter(Objects::nonNull).collect(toSet());
  }

  @Override
  protected Class<AbstractErgebnisKonfliktLosoptionenCustomData> getErgebnisKonfliktCustomDataClass() {
    return AbstractErgebnisKonfliktLosoptionenCustomData.class;
  }

  @Override
  protected void addErgebnisKonfliktLoesungProperties(FormBuilder formBuilder, ErgebnisKonflikt ergebnisKonflikt) {
    long anzahlZuLosen = getCustomData(ergebnisKonflikt).getAnzahlZuLosen();

    if (anzahlZuLosen == 1) {
      formBuilder.addProperty(createErgebnisKonfliktSelectOneMenuProperty(ergebnisKonflikt));
    }

    if (anzahlZuLosen > 1) {
      formBuilder.addProperty(createErgebnisKonfliktAnzahlZuLosenProperty(ergebnisKonflikt)).readonly();
      formBuilder.addProperty(createErgebnisKonfliktLosoptionenPickListProperty(ergebnisKonflikt));
      formBuilder.required().withValidator(new PickListTargetSizeRangeValidator()) //
          .withAttribute(PickListTargetSizeRangeValidator.MIN_SIZE_ATTRIBUTE_NAME, anzahlZuLosen) //
          .withAttribute(PickListTargetSizeRangeValidator.MAX_SIZE_ATTRIBUTE_NAME, anzahlZuLosen);
    }
  }

  private ErgebnisKonfliktLosoptionSelectOneMenuProperty createErgebnisKonfliktSelectOneMenuProperty(ErgebnisKonflikt ergebnisKonflikt) {
    List<ErgebnisKonfliktLosoption> losoptionenGelost = getLosoptionenGelost(ergebnisKonflikt);
    if (losoptionenGelost.size() > 1) {
      throw new IllegalStateException("Die Anzahl der gelosten Ergebniskonfliktoptionen ist höher als erwartet." + losoptionenGelost);
    }
    return new ErgebnisKonfliktLosoptionSelectOneMenuProperty(getLosoptionenVerfuegbar(ergebnisKonflikt), getCustomData(ergebnisKonflikt), losoptionenGelost.stream().findAny().orElse(null));
  }

  private ErgebnisKonfliktAnzahlZuLosenProperty createErgebnisKonfliktAnzahlZuLosenProperty(ErgebnisKonflikt ergebnisKonflikt) {
    return new ErgebnisKonfliktAnzahlZuLosenProperty(getCustomData(ergebnisKonflikt));
  }

  private ErgebnisKonfliktLosoptionPickListProperty createErgebnisKonfliktLosoptionenPickListProperty(ErgebnisKonflikt ergebnisKonflikt) {
    return new ErgebnisKonfliktLosoptionPickListProperty(getCustomData(ergebnisKonflikt), getLosoptionenVerfuegbar(ergebnisKonflikt), getLosoptionenGelost(ergebnisKonflikt));
  }

  @Override
  protected String createErgebnisKonfliktLoesungBeschreibung(AbstractErgebnisKonfliktLosoptionenCustomData ergebnisKonfliktCustomData, Messages messages) {
    List<ErgebnisKonfliktLosoption> losoptionenGelost = ergebnisKonfliktCustomData.getLosoptionenGelost(wahlvorschlagDAO, kandidaturDAO, listenverbindungDAO, politischeGruppeDAO,
        wahldurchfuehrungsgebietDAO, getMessages());

    return ergebnisKonfliktCustomData.createLoesungBeschreibung(losoptionenGelost);
  }

  protected List<ErgebnisKonfliktLosoption> getLosoptionenVerfuegbar(ErgebnisKonflikt ergebnisKonflikt) {
    return getCustomData(ergebnisKonflikt).getLosoptionenVerfuegbar(wahlvorschlagDAO, kandidaturDAO, listenverbindungDAO, politischeGruppeDAO, wahldurchfuehrungsgebietDAO, messages);
  }

  private List<ErgebnisKonfliktLosoption> getLosoptionenGelost(ErgebnisKonflikt ergebnisKonflikt) {
    return getCustomData(ergebnisKonflikt).getLosoptionenGelost(wahlvorschlagDAO, kandidaturDAO, listenverbindungDAO, politischeGruppeDAO, wahldurchfuehrungsgebietDAO, messages);
  }
}
