
package de.ivu.elect.presentation.gebietsbaum;

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

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

import de.ivu.elect.business.gebietsbaum.boundary.GebietExtendedDAO;
import de.ivu.elect.business.gebietsbaum.boundary.GebietSessionSelect;
import de.ivu.elect.business.gebietsbaum.control.EntityMitWurzelgebiet;
import de.ivu.elect.business.gebietsbaum.control.EntityMitWurzelgebietDAO;
import de.ivu.elect.business.gebietsbaum.control.GebietByBreadthFirstComparator;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.wahl.boundary.WahlSelectChangeEvent;
import de.ivu.elect.business.wahl.boundary.WahlSessionSelector;
import de.ivu.elect.business.wahl.boundary.WahlterminSelectChangeEvent;
import de.ivu.elect.business.wahl.boundary.WahlterminSessionSelect;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.WahlOderWahltermin;
import de.ivu.elect.business.wahl.entity.Wahltermin;
import de.ivu.elect.jee.faces.FacesMessageUtil;
import de.ivu.elect.presentation.security.GebietSecurity;

public class SetzeWurzelgebietSelectChangeListener {

  @Inject
  private transient GebietExtendedDAO gebietDAO;

  @Inject
  private transient GebietSessionSelect gebietSelect;

  @Inject
  private transient GebietSecurity gebietSecurity;

  @Inject
  private transient WahlterminSessionSelect wahlterminSessionSelect;

  @Inject
  private transient WahlSessionSelector wahlSessionSelector;

  public SetzeWurzelgebietSelectChangeListener() {
    super();
  }

  public boolean isBetrachteWahltermin() {
    return true;
  }

  public boolean isBetrachteWahl() {
    return false;
  }

  public void listenWahlChangeEvent(@Observes(notifyObserver = Reception.ALWAYS) WahlSelectChangeEvent event) {
    if (isBetrachteWahl()) {
      setzeWurzelgebiet(event.getNeueEntity());
    }
  }

  public void listenWahlChangeEvent(@Observes(notifyObserver = Reception.ALWAYS) WahlterminSelectChangeEvent event) {
    if (isBetrachteWahltermin()) {
      setzeWurzelgebiet(event.getNeueEntity());
    }
  }

  public void setzeWurzelgebiet(EntityMitWurzelgebiet entityMitWurzelgebiet) {
    if (entityMitWurzelgebiet == null) {
      gebietSelect.setEntity((Gebiet) null);

      return;
    }

    Gebiet wurzelgebiet = entityMitWurzelgebiet.getWurzelgebiet(EntityMitWurzelgebietDAO.fromDao(gebietDAO));

    if (wurzelgebiet == null || isRechtVorhanden(wurzelgebiet)) {
      gebietSelect.setEntity(wurzelgebiet);

      return;
    }

    List<Gebiet> alleGebiete = new ArrayList<>(getAlleGebiete(entityMitWurzelgebiet, gebietDAO));
    alleGebiete.sort(new GebietByBreadthFirstComparator());

    for (Gebiet gebiet : alleGebiete) {
      if (isRechtVorhanden(gebiet)) {
        gebietSelect.setEntity(gebiet);

        return;
      }
    }

    FacesMessageUtil.addWarnMessage("gebiet.kein.recht.fuer.ein.gebiet");
  }

  private boolean isRechtVorhanden(Gebiet wurzelgebiet) {
    return gebietSecurity.getEinsehenGebietSecurity().isRechtVorhanden(wurzelgebiet);
  }

  private Collection<Gebiet> getAlleGebiete(EntityMitWurzelgebiet entityMitWurzelgebiet, GebietExtendedDAO gebietDAO) {
    if (isBetrachteWahl()) {
      return gebietDAO.findByWahl((Wahl) entityMitWurzelgebiet);
    }

    if (isBetrachteWahltermin()) {
      return gebietDAO.findByWahltermin((Wahltermin) entityMitWurzelgebiet);
    }

    throw new IllegalStateException();
  }

  private WahlOderWahltermin getWahlOderWahltermin() {
    if (isBetrachteWahl()) {
      return wahlSessionSelector.getEntity();
    }
    if (isBetrachteWahltermin()) {
      return wahlterminSessionSelect.getEntity();
    }
    throw new IllegalStateException();
  }

  // ELECT-8130
  public void aktualisierWurzelgebietWennNotwendig() {
    if (!gebietSelect.isSelected()) {
      setzeWurzelgebiet(getWahlOderWahltermin());
    }
  }

}
