
package de.ivu.elect.presentation.wahl;

import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.security.UseCaseSecure;
import de.ivu.elect.business.wahl.boundary.WahlExtendedDAO;
import de.ivu.elect.business.wahl.boundary.WahlterminExtendedDAO;
import de.ivu.elect.business.wahl.boundary.WahlterminFactory;
import de.ivu.elect.business.wahl.control.WahlUtils;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.Wahltermin;
import de.ivu.elect.business.wahl.entity.WahlterminProperties;
import de.ivu.elect.business.wahl.entity.WahlterminProperties.WahldatumProperty;
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.redirect.Redirect;
import de.ivu.elect.presentation.hilfe.OnlineHilfeId;
import de.ivu.elect.presentation.wahl.form.WahlViewFormBuilder;

import javax.annotation.Nullable;
import javax.faces.application.FacesMessage;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import static java.util.Collections.emptyList;
import static java.util.Objects.isNull;

@OnlineHilfeId("389")
@Named(AbstractWahlEditView.COMPONENT_NAME)
public class WahlEditView extends AbstractWahlEditView implements WahldatumWahlView {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient WahlterminExtendedDAO wahlterminDao;

  @Inject
  private transient WahlterminFactory wahlterminFactory;

  @Inject
  private transient WahlViewFormBuilder viewFormBuilder;

  @Inject
  private transient WahlExtendedDAO wahlExtendedDAO;
  private Wahltermin wahlterminEdited;

  public WahlEditView() {
    super();
  }

  @Override
  @PreConditionCheck
  @Nullable
  public String checkPreCondition() {
    if (getEntity() == null) {
      return cancel();
    }

    return null;
  }

  @Override
  protected boolean isGebietBearbeitenRechtPruefen() {
    return false;
  }

  @Override
  public void addProperties(FormBuilder formBuilder, Wahl wahl) {
    viewFormBuilder.addProperties(formBuilder, wahl, getWahlterminWahldatumProperty());
  }

  @Override
  public WahldatumProperty getWahlterminWahldatumProperty() {
    return new WahldatumProperty(getWahlterminEdited());
  }

  @Override
  public WahlterminProperties.NummerProperty getWahlterminWahlnummerProperty() {
    return new WahlterminProperties.NummerProperty(getWahlterminEdited());
  }

  @Override
  public List<FacesMessage> getWahlterminWahldatumHints() {
    List<FacesMessage> result = new ArrayList<>();

    Collection<Wahl> wahlenHavingOtherWahlterminButSameWahldatum = findWahlenHavingOtherWahlterminButSameWahldatum(getWahlterminEdited().getWahldatum(), getWahlterminEdited().getNummer());

    if (!wahlenHavingOtherWahlterminButSameWahldatum.isEmpty()) {
      // ELECTMUC-1106
      result.add(new FacesMessage(FacesMessage.SEVERITY_ERROR, "", getMessage("wahl.edit.wahltermin.not.unique.message", getMessage("wahl.wahltermin.not.unique.message",
          WahlUtils.getWahlartenAsString(wahlenHavingOtherWahlterminButSameWahldatum), getWahlterminEdited().getWahldatum(), wahlenHavingOtherWahlterminButSameWahldatum.size()))));
    }

    return result;
  }

  @Override
  public AdvancedDynaFormModel getModel() {
    return super.getModel();
  }

  private Collection<Wahl> findWahlenHavingOtherWahlterminButSameWahldatum(Date wahldatum, String nummer) {
    if (isEntitySet()) { // ELECT-5317
      return edit.findWahlenHavingOtherWahlterminButSameWahldatum(wahlterminDao, getEntity().getMandant(), wahldatum, nummer, getEntity().getWahltermin());
    }

    return emptyList();
  }

  private Wahltermin getWahlterminEdited() {
    if (isNull(wahlterminEdited)) {
      wahlterminEdited = wahlterminFactory.create();
      wahlterminEdited.setWahldatum(getEntity().getWahldatum());
      wahlterminEdited.setNummer(getEntity().getWahlterminNummer());
      wahlterminEdited.setMandant(getMandant());
    }

    return wahlterminEdited;
  }

  @Override
  @Redirect
  @UseCaseSecure(UseCasePermission.WAHL_EDIT)
  public String save() {
    Wahl wahl = getEntity();

    preSave(wahl);

    edit.save(wahl, wahl.getMandant(), getWahlterminEdited().getWahldatum(), getWahlterminEdited().getNummer());

    addMessageSaveSuccess(wahl);

    conversationStore.close();

    return goBack();
  }

  @Override
  protected void addMessageSaveSuccess(Wahl wahl) {
    super.addMessageSaveSuccess(wahl);

    checkQuorum(wahl); // ELECT-8461
  }

  protected void checkQuorum(Wahl template) {
    Wahl wahl = extendedDAO.attach(template);

    // ELECT-8461, ELECTKOM-2002, cf. WahlCreateView#checkQuorum!!!
    if (wahl != null && wahl.getQuorumProzenthuerde() == null && wahl.isWahlMitWahlgebieten()) { // KEIN Wahlgebiet -> kein Quorum erforderlich/keine Sitzberechnung mit Prozenthürde...
      String msgKey = "wahl.edit.quorum.prozenthuerde.nicht.gesetzt";

      if (wahl.isWahlMitQuorum()) {
        msgKey = "wahl.edit.quorum.nicht.gesetzt";
      } else if (wahl.isWahlMitProzenthuerde()) {
        msgKey = "wahl.edit.prozenthuerde.nicht.gesetzt";
      }

      addWarningMessage(msgKey);
    }
  }

  protected void preSave(Wahl wahl) {
    // nichts zu tun
  }

  @Override
  @Redirect
  @UseCaseSecure(UseCasePermission.WAHL_DELETE)
  public String delete() {
    Wahl wahl = getEntity();
    boolean cleanAfterDelete = checkCleanAfterDelete();
    String delete = super.delete(wahl);
    if (cleanAfterDelete) {
      postClean(); // nur im Erfolgsfall ausführen ELECTVAPP-1959
    }
    return delete;
  }

  protected boolean checkCleanAfterDelete() {
    return false;
  }

  protected void postClean() {
    // nichts zu tun
  }

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

  @Override
  public boolean isWahlnummerRendered() {
    return isWahldatumRendered();
  }

  @Override
  public boolean isWahldatumReadonly() {
    return isWahlaufgeteilt(); // ELECT-16933
  }

  @Override
  public boolean isWahlnummerReadonly() {
    return isWahlaufgeteilt(); // ELECT-16933
  }

  private boolean isWahlaufgeteilt() {
    return getEntity() != null && getEntity().isWahlAufgeteiltOderBerichtetAn(wahlExtendedDAO);
  }


  public String getPageTitle() {
    return getMessage("entity.edit.page.title", entityMeta.getEinzahlMessage());
  }

  public String getPageHeader() {
    return getMessage("entity.edit.page.header", entityMeta.getEinzahlMessage());
  }

}
