
package de.ivu.elect.presentation.gebietsbaum;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Nullable;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.event.Observes;
import javax.enterprise.event.Reception;
import javax.inject.Inject;
import javax.inject.Named;

import de.ivu.elect.business.gebietsbaum.boundary.GebietsgruppierungStatus;
import de.ivu.elect.business.gebietsbaum.control.GebietByPositionComparator;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.Gebietsgruppierung;
import de.ivu.elect.business.gebietsbaum.entity.GebietsgruppierungMeta;
import de.ivu.elect.business.gebietsbaum.entity.GebietsgruppierungStatusResult;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.wahl.boundary.WahlSelectChangeEvent;
import de.ivu.elect.jee.faces.PreConditionCheck;
import de.ivu.elect.jee.presentation.charts.PieChartModelBuilder;
import de.ivu.elect.jee.presentation.dynamicform.AdvancedDynaFormModel;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.dynamicform.LambdaStringSelectOneProperty;
import de.ivu.elect.jee.presentation.dynamicform.ReadOnlyStringProperty;
import de.ivu.elect.jee.presentation.redirect.Redirect;
import de.ivu.elect.presentation.AbstractElectStatusuebersichtView;
import de.ivu.elect.presentation.View;
import de.ivu.elect.presentation.charts.ChartColor;
import de.ivu.elect.presentation.hilfe.OnlineHilfeId;

@RequestScoped
@OnlineHilfeId(value = "533")
@Named(GebietsgruppierungStatusView.COMPONENT_NAME)
@View(viewId = GebietsgruppierungStatusView.VIEW_ID, useCase = UseCasePermission.GEBIETSGRUPPIERUNG_SEARCH)
public class GebietsgruppierungStatusView extends AbstractElectStatusuebersichtView<Gebietsgruppierung> {

  public static final String VIEW_ID = "/gebietsbaum/gebietsgruppierung-status.xhtml";

  public static final String COMPONENT_NAME = "gebietsgruppierungStatusView";

  private static final long serialVersionUID = 1L;

  @Inject
  private transient GebietsgruppierungStatus gebietsgruppierungStatus;

  @Inject
  private transient GebietsgruppierungMeta gebietsgruppierungMeta;

  @Inject
  private transient ChartColor chartColor;

  @Inject
  private transient GebietsgruppierungStatusStore gebietsgruppierungStatusStore;

  private transient GebietsgruppierungStatusResult gebietsgruppierungStatusResult;

  @Inject
  private transient GebietNummerFormatter gebietNummerFormatter;

  private transient AdvancedDynaFormModel doppeltNichtZugeordnetModel;

  public GebietsgruppierungStatusView() {
    super();
  }

  @Nullable
  @PreConditionCheck
  public String checkCondition() {
    if (!isWahlSelected()) {
      return getStartViewId();
    }

    return null;
  }

  public List<String> getGruppierungsartarten() {
    return gebietsgruppierungStatus.getArten(getSelectedWahl());
  }

  public void onWahlSelectChangeEvent(@Observes(notifyObserver = Reception.IF_EXISTS) WahlSelectChangeEvent event) {
    reset();

  }

  @Nullable
  @Override
  @Redirect
  public String reset() {
    gebietsgruppierungStatusStore.setGruppierungsart(null);
    gebietsgruppierungStatusResult = null;
    doppeltNichtZugeordnetModel = null;
    return super.reset();
  }

  @Override
  protected void resetModel() {
    doppeltNichtZugeordnetModel = null;
    gebietsgruppierungStatusResult = null;
    super.resetModel();
  }

  @Override
  protected void fillStatusPieChartModel(PieChartModelBuilder modelBuilder) {

    GebietsgruppierungStatusResult result = getGebietsgruppierungStatusResult();
    Map<String, String> farbenMap = chartColor.bestimmeFarben(new ArrayList<>(result.getAnzahlErfassungsgebieteProName().keySet()));

    for (Map.Entry<String, Long> entry : result.getAnzahlErfassungsgebieteProName().entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).collect(Collectors.toList())) {
      modelBuilder.add(entry.getKey() + " - " + entry.getValue(), entry.getValue(), farbenMap.get(entry.getKey()));
    }

    if (!result.getGebieteMehrfach().isEmpty()) {
      modelBuilder.add(getMessage("gebietsgruppierung.gebiete.mehrfach.anzahl.pie") + " - " + result.getGebieteMehrfach().size(), result.getGebieteMehrfach().size(), chartColor.getAchtungFarbe());
    }

    if (!result.getGebieteOhneGruppierung().isEmpty()) {
      modelBuilder.add(getMessage("gebietsgruppierung.gebiete.nicht.anzahl.pie") + " - " + result.getGebieteOhneGruppierung().size(), result.getGebieteOhneGruppierung().size(),
          chartColor.getNichtGesetztFarbe());
    }

  }

  @Override
  protected Gebietsgruppierung getEntity() {
    return new Gebietsgruppierung();
  }

  @Override
  protected void addProperties(FormBuilder formBuilder, Gebietsgruppierung entity) {
    super.addProperties(formBuilder, entity);
    List<String> gruppierungsartarten = getGruppierungsartarten();
    formBuilder.addProperty(new LambdaStringSelectOneProperty(gebietsgruppierungMeta.getGebietsgruppierungArtEinzahlMessage(), true, gebietsgruppierungStatusStore::setGruppierungsart,
        gebietsgruppierungStatusStore::getGruppierungsart, gruppierungsartarten, gruppierungsartarten.size() != 1));
  }

  public boolean isArtSet() {
    return !getGebietsgruppierungStatusResult().isEmpty();
  }

  public GebietsgruppierungStatusResult getGebietsgruppierungStatusResult() {
    if (gebietsgruppierungStatusResult == null) {
      gebietsgruppierungStatusResult = gebietsgruppierungStatus.getGebietsgruppierungStatus(getSelectedWahl(), gebietsgruppierungStatusStore.getGruppierungsart());
    }
    return gebietsgruppierungStatusResult;
  }

  public AdvancedDynaFormModel getDoppeltNichtZugeordnetModel() {
    if (doppeltNichtZugeordnetModel == null) {
      doppeltNichtZugeordnetModel = createDoppeltNichtZugeordnetModel();
    }
    return doppeltNichtZugeordnetModel;
  }

  private AdvancedDynaFormModel createDoppeltNichtZugeordnetModel() {
    FormBuilder formBuilder = createFormBuilder();

    GebietsgruppierungStatusResult result = getGebietsgruppierungStatusResult();

    if (!result.getGebieteMehrfach().isEmpty()) {
      formBuilder.addProperty(new ReadOnlyStringProperty(getMessage("gebietsgruppierung.gebiete.mehrfach.anzahl"), erzeugeMehrfachGebiete(result.getGebieteMehrfach())));
    }

    if (!result.getGebieteOhneGruppierung().isEmpty()) {
      formBuilder.addProperty(new ReadOnlyStringProperty(getMessage("gebietsgruppierung.gebiete.nicht.anzahl"), erzeugeNichtGebiete(result.getGebieteOhneGruppierung())));
    }

    return formBuilder.createModel();

  }

  private String erzeugeNichtGebiete(List<Gebiet> gebieteOhneGruppierung) {
    gebieteOhneGruppierung.sort(new GebietByPositionComparator());
    return gebieteOhneGruppierung.stream().map(g -> gebietNummerFormatter.getDarstellung(g)).collect(Collectors.joining(", "));
  }

  private String erzeugeMehrfachGebiete(Map<Gebiet, List<Gebietsgruppierung>> gebieteMehrfach) {

    GebietByPositionComparator comp = new GebietByPositionComparator();
    return gebieteMehrfach.entrySet().stream().sorted((u, v) -> comp.compare(u.getKey(), v.getKey()))
        .map(e -> gebietNummerFormatter.getDarstellung(e.getKey()) + " (" + e.getValue().stream().map(Gebietsgruppierung::getName).sorted().collect(Collectors.joining(", ")) + ")")
        .collect(Collectors.joining(", "));
  }
}
