
package de.ivu.elect.presentation.wahl;

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

import javax.annotation.Nullable;
import javax.faces.application.FacesMessage;
import javax.inject.Inject;
import javax.inject.Named;

import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.security.UseCaseSecure;
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 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;

  private Wahltermin wahlterminEdited;

  public WahlEditView() {
    super();
  }

  @Override
  @PreConditionCheck
  @Nullable
  public String checkPreCondition() {
    if (isNull(getEntity())) {
      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 entity) {
    super.addMessageSaveSuccess(entity);
    // ELECT-8461
    checkQuorum(entity);
  }

  protected void checkQuorum(Wahl entity) {
    if (entity.getQuorumProzenthuerde() == null) {
      addWarningMessage("wahl.edit.quorum.prozenthuerde.nicht.gesetzt");
    }
  }

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

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

    preDelete();

    return super.delete(wahl);
  }

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

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

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

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

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

}
