
package de.ivu.elect.presentation.niederschrift;

import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.enterprise.event.Observes;
import javax.enterprise.event.Reception;
import javax.inject.Inject;
import javax.inject.Named;

import org.apache.deltaspike.core.api.scope.ConversationGroup;
import org.apache.deltaspike.core.api.scope.ViewAccessScoped;

import de.ivu.elect.business.niederschrift.boundary.AbstractNiederschriftSearchParameters;
import de.ivu.elect.business.niederschrift.boundary.NiederschriftListConversationStore;
import de.ivu.elect.business.niederschrift.boundary.NiederschriftSearchParameters;
import de.ivu.elect.business.niederschrift.boundary.WasNiederschriftStatusAenderungBoundaryCreate;
import de.ivu.elect.business.niederschrift.entity.Niederschrift;
import de.ivu.elect.business.niederschrift.entity.NiederschriftArt;
import de.ivu.elect.business.niederschrift.entity.NiederschriftConstants;
import de.ivu.elect.business.niederschrift.entity.NiederschriftStatusAenderung;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.security.UseCaseSecure;
import de.ivu.elect.business.wahl.boundary.WahlSelectChangeEvent;
import de.ivu.elect.jee.faces.PreConditionCheck;
import de.ivu.elect.jee.presentation.dynamicform.AdvancedDynaFormModel;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.dynamicform.ReadOnlyLongProperty;
import de.ivu.elect.jee.presentation.redirect.Redirect;
import de.ivu.elect.presentation.View;
import de.ivu.elect.presentation.niederschrift.form.NiederschriftSearchFormBuilder;
import de.ivu.elect.presentation.niederschrift.form.NiederschriftStatusAenderungViewFormBuilder;

@Named(NiederschriftStatusAenderungBulkCreateView.COMPONENT_NAME)
@ViewAccessScoped // Konditionelle Anzeige eines Hinweisdialoges!
@View(viewId = NiederschriftStatusAenderungBulkCreateView.VIEW_ID, useCase = UseCasePermission.NIEDERSCHRIFT_STATUS_AENDERUNG_CREATE)
public class NiederschriftStatusAenderungBulkCreateView extends AbstractNiederschriftStatusAenderungCreateView {

  private static final long serialVersionUID = 1L;

  public static final String COMPONENT_NAME = "niederschriftStatusAenderungBulkCreateView";

  public static final String VIEW_ID = "/niederschrift/niederschrift-status-aenderung-bulk-create.xhtml";

  @Inject
  private transient WasNiederschriftStatusAenderungBoundaryCreate niederschriftStatusAenderungBoundaryCreate;

  @Inject
  @ConversationGroup(AbstractNiederschriftSearchParameters.class)
  private transient NiederschriftSearchParameters niederschriftSearchParameters;

  @Inject // Cf. NiederschriftSearchView!
  @ConversationGroup(NiederschriftListConversationStore.class)
  private transient NiederschriftListConversationStore niederschriftenSelected;

  @Inject
  private transient NiederschriftSearchFormBuilder niederschriftSearchFormBuilder;

  @Inject
  private transient NiederschriftStatusAenderungViewFormBuilder niederschriftStatusAenderungViewFormBuilder;

  private boolean dlgSaveConfirmedRequired;

  public NiederschriftStatusAenderungBulkCreateView() {
    super();
  }

  @Override
  protected String getViewId() {
    return VIEW_ID;
  }

  @Override
  protected String getParentViewId() {
    return NiederschriftSearchView.VIEW_ID;
  }

  @PreConditionCheck
  public String checkPreCondition() {
    if (isAnyNiederschriftSelected()) {
      return null;
    }

    return getParentViewId();
  }

  private boolean isAnyNiederschriftSelected() {
    return !getNiederschriftenSelected().isEmpty();
  }

  public List<Niederschrift> getNiederschriftenSelected() {
    return niederschriftenSelected.get();
  }

  public AdvancedDynaFormModel getNiederschriftenSelectedModel() {
    FormBuilder formBuilder = createFormBuilder();

    Collection<Niederschrift> niederschriften = getNiederschriftenSelected();
    formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("niederschrift.status.aenderung.bulk.create.gesamtzahl.label"), (long) niederschriften.size()));

    if (!niederschriften.isEmpty()) {
      Map<NiederschriftArt, Long> anzahlNiederschriftenPerNiederschriftArt = niederschriften.stream() //
          .filter(niederschrift -> niederschrift.getNiederschriftArt() != null) //
          .collect(groupingBy(Niederschrift::getNiederschriftArt, counting()));

      for (NiederschriftArt niederschriftArt : NiederschriftArt.values()) {
        formBuilder.addProperty(
            new ReadOnlyLongProperty(getMessage("NiederschriftArt." + niederschriftArt.name() + ".mehrzahl"), anzahlNiederschriftenPerNiederschriftArt.getOrDefault(niederschriftArt, 0L)));
      }
    }

    FormBuilder formBuilderSearchParameters = createFormBuilder();
    niederschriftSearchFormBuilder.addProperties(formBuilderSearchParameters, niederschriftSearchParameters, true);

    if (formBuilderSearchParameters.createModel().isAnyPropertyAdded()) {
      formBuilder.addSeparator("component.filter.panel.header");
      niederschriftSearchFormBuilder.addProperties(formBuilder, niederschriftSearchParameters, true);
    }

    return formBuilder.createModel();
  }

  @Override
  public void addProperties(FormBuilder formBuilder, NiederschriftStatusAenderung niederschriftStatusAenderung) {
    niederschriftStatusAenderungViewFormBuilder.addProperties(formBuilder, niederschriftStatusAenderung, false);
  }

  public boolean isDlgSaveConfirmedRequired() {
    return dlgSaveConfirmedRequired;
  }

  public void setDlgSaveConfirmedRequired(boolean dlgSaveConfirmedRequired) {
    this.dlgSaveConfirmedRequired = dlgSaveConfirmedRequired;
  }

  public boolean isBtnSaveConfirmedRendered() {
    return super.isBtnSaveRendered();
  }

  public String getBtnSaveConfirmedLabel() {
    return super.getBtnSaveLabel();
  }

  @Redirect
  @UseCaseSecure(UseCasePermission.NIEDERSCHRIFT_STATUS_AENDERUNG_CREATE)
  public String saveConfirmed() {
    setDlgSaveConfirmedRequired(true);

    return getViewId();
  }

  @Override
  public boolean isBtnSaveRendered() {
    return false; // Cf. NiederschriftStatusAenderungBulkCreateView#isBtnSaveConfirmedRendered!
  }

  @Override
  public String getBtnSaveLabel() {
    return getMessage("niederschrift.status.aenderung.create.save.all");
  }

  @Override
  @Redirect
  @UseCaseSecure(UseCasePermission.NIEDERSCHRIFT_STATUS_AENDERUNG_CREATE)
  public String save() {
    setDlgSaveConfirmedRequired(false);

    NiederschriftStatusAenderung template = getEntity();

    Collection<Niederschrift> niederschriften = getNiederschriftenSelected();
    Collection<NiederschriftStatusAenderung> niederschriftStatusAenderungen = new ArrayList<>();

    for (Niederschrift niederschrift : niederschriften) {
      NiederschriftStatusAenderung niederschriftStatusAenderung = new NiederschriftStatusAenderung();
      template.copyEntityAttributesToOtherEntity(niederschriftStatusAenderung);

      niederschriftStatusAenderung.setNiederschriftOhneUpdateBeziehung(niederschrift); // Wird beim Speichern attached und gesetzt!
      niederschriftStatusAenderung.setZeitstempel(new Date());

      niederschriftStatusAenderungen.add(niederschriftStatusAenderung);
    }

    niederschriftStatusAenderungBoundaryCreate.save(niederschriftStatusAenderungen);

    long niederschriftenCount = niederschriftStatusAenderungen.size();

    addInfoMessage("entity.create.action.save.success.message",
        niederschriftenCount == 1
            ? getMessage(NiederschriftConstants.MESSAGE_KEY_ENTITY_EINZAHL)
            : getUserLocale().formatNumber(niederschriftenCount) + " " + getMessage(NiederschriftConstants.MESSAGE_KEY_ENTITY_MEHRZAHL));

    return cancel();
  }

  @Override
  @Redirect
  public String reset() {
    // NICHT die ausgewählten Niederschriften zurücksetzen!!!

    setDlgSaveConfirmedRequired(false);

    return super.reset();
  }

  @Override
  @Redirect
  public String cancel() {
    resetNiederschriftenSelected();

    return super.cancel();
  }

  private void resetNiederschriftenSelected() {
    niederschriftenSelected.reset();
    niederschriftenSelected.close();
  }

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