package de.ivu.elect.presentation.wahl;

import de.ivu.elect.business.CurrentCustomer;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.security.UseCaseSecure;
import de.ivu.elect.business.wahl.boundary.WahlterminCopyCreate;
import de.ivu.elect.business.wahl.boundary.WahlterminExtendedDAO;
import de.ivu.elect.business.wahl.boundary.WahlterminFactory;
import de.ivu.elect.business.wahl.control.WahlterminNummerRelevant;
import de.ivu.elect.business.wahl.entity.Wahltermin;
import de.ivu.elect.business.wahl.entity.WahlterminCopyEntity;
import de.ivu.elect.business.wahl.entity.WahlterminMeta;
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.jee.presentation.redirect.Redirect;
import de.ivu.elect.presentation.AbstractElectCreateView;
import de.ivu.elect.presentation.View;
import de.ivu.elect.presentation.hilfe.OnlineHilfeId;
import de.ivu.elect.presentation.wahl.action.WahlterminZurBearbeitungAuswaehlenAction;
import de.ivu.elect.presentation.wahl.form.WahlterminViewFormBuilder;

import javax.annotation.Nullable;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@RequestScoped
@OnlineHilfeId("723")
@Named(WahlterminCopyCreateView.COMPONENT_NAME)
@View(viewId = WahlterminCopyCreateView.VIEW_ID, useCase = UseCasePermission.WAHLTERMIN_COPY_CREATE)
public class WahlterminCopyCreateView extends AbstractElectCreateView<Wahltermin> {

  public static final String COMPONENT_NAME = "wahlterminCopyCreateView";

  public static final String VIEW_ID = "/wahl/wahltermin-copy-create.xhtml";

  private static final long serialVersionUID = 1L;

  private static final String PARENT_VIEW_ID = WahlterminSearchView.VIEW_ID;

  private final Set<WahlterminCopyEntity> auswahlZuKopieren = new HashSet<>();

  @Inject
  private transient WahlterminCopyCreate wahlterminCopyCreate;

  @Inject
  private transient WahlterminFactory wahlterminFactory;

  @Inject
  private transient WahlterminMeta wahlterminMeta;

  @Inject
  private transient WahlterminZurBearbeitungAuswaehlenAction wahlterminZurBearbeitungAuswaehlenAction;

  @Inject
  private transient WahlterminViewFormBuilder viewFormBuilder;

  @Inject
  private transient WahlterminExtendedDAO wahlterminExtendedDAO;

  @Inject
  private transient CurrentCustomer currentCustomer;

  @Inject
  private transient WahlterminNummerRelevant wahlterminNummerRelevant;

  private transient Wahltermin entity;

  public WahlterminCopyCreateView() {
    super();
  }

  protected String getViewId() {
    return VIEW_ID;
  }

  protected String getParentViewId() {
    return PARENT_VIEW_ID;
  }

  @PreConditionCheck
  @Nullable
  public String checkPreCondition() {
    if (!isWahlterminSelected()) {
      return getStartViewId();
    }

    return null;
  }

  protected List<WahlterminCopyEntity> getInitialeAuswahl() {
    return WahlterminCopyEntity.getEntitiesForCustomer(currentCustomer.getCustomer());
  }

  @PostConstruct
  public void init() {
    setEntity(wahlterminFactory.create());
    auswahlZuKopieren.addAll(getInitialeAuswahl());
  }

  @Override
  public Wahltermin getEntity() {
    return entity;
  }

  protected void setEntity(Wahltermin entity) {
    if (wahlterminNummerRelevant.isNummerRelevant()) {
      entity.setNummer(null); // Eingabe erzwingen
    }
    entity.setMandant(getMandant()); // ELECTMUC-2413
    this.entity = entity;
  }

  @Override
  protected void addProperties(FormBuilder formBuilder, Wahltermin wahltermin) {
    viewFormBuilder.addProperties(formBuilder, wahltermin);

    formBuilder.addSeparator("wahltermin.copy.zu.kopieren");

    for (WahlterminCopyEntity wahlterminCopyEntity : WahlterminCopyEntity.getEntitiesForCustomer(currentCustomer.getCustomer())) {
      addWahlterminCopyEntity(formBuilder, wahlterminCopyEntity);
    }
  }

  private void addWahlterminCopyEntity(FormBuilder formBuilder, WahlterminCopyEntity entity) {
    formBuilder.addProperty(new LambdaBooleanProperty(messages.lokalisiere(entity), false, e -> {
      if (e) {
        auswahlZuKopieren.add(entity);
      } else {
        auswahlZuKopieren.remove(entity);
      }
    }, () -> auswahlZuKopieren.contains(entity)));
  }

  @Override
  public boolean isBtnSaveRendered() {
    return hasPermission(UseCasePermission.WAHLTERMIN_COPY_CREATE);
  }

  @Override
  public String getBtnSaveLabel() {
    return getMessage("entity.edit.action.save");
  }

  @Override
  @Redirect
  @UseCaseSecure(UseCasePermission.WAHLTERMIN_COPY_CREATE)
  public String save() {
    Wahltermin neuerWahltermin = wahlterminExtendedDAO.refresh(createCopy(getEntity()));
    addMessageSaveSuccess(neuerWahltermin);
    return resolveGoBack(neuerWahltermin);
  }

  protected String resolveGoBack(Wahltermin stichwahltermin) {
    if (wahlterminZurBearbeitungAuswaehlenAction.isActionPossible(stichwahltermin)) {
      goBack(getParentViewId()); // View vom Stack nehmen
      return wahlterminZurBearbeitungAuswaehlenAction.action(stichwahltermin);
    }

    return goBack(getParentViewId());
  }

  protected Wahltermin createCopy(Wahltermin copyWahltermin) {
    return wahlterminCopyCreate.createWahlterminCopy(getSelectedWahltermin(), copyWahltermin, auswahlZuKopieren);
  }

  protected void addMessageSaveSuccess(Wahltermin entity) {
    addInfoMessage("entity.create.action.save.success.message", wahlterminMeta.getEinzahlMessage());
    if (!auswahlZuKopieren.isEmpty()) {
      for (WahlterminCopyEntity wahlterminCopyEntity : WahlterminCopyEntity.getEntitiesForCustomer(currentCustomer.getCustomer())) {
        if (auswahlZuKopieren.contains(wahlterminCopyEntity)) {
          addInfoMessage("wahltermin.entity.kopiert", messages.lokalisiere(wahlterminCopyEntity));
        }
      }
    }
  }

  @Override
  public boolean isBtnResetRendered() {
    return true;
  }

  @Override
  @Redirect
  public String reset() {
    init();
    auswahlZuKopieren.clear();
    auswahlZuKopieren.addAll(getInitialeAuswahl());
    return getViewId();
  }

  @Override
  public boolean isBtnCancelRendered() {
    return true;
  }

  @Override
  @Redirect
  public String cancel() {
    return goBack(getParentViewId());
  }
}
