
package de.ivu.elect.business.wahl.entity;

import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.stream.Collectors;

import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Transient;

import de.ivu.elect.business.gebietsbaum.control.EntityMitWurzelgebiet;
import de.ivu.elect.business.gebietsbaum.control.EntityMitWurzelgebietDAO;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.mandant.entity.EntityMitMandant;
import de.ivu.elect.business.wahl.control.WahlByPositionComparator;
import de.ivu.elect.jee.faces.FacesMessageUtil;

public abstract class AbstractWahltermin implements WahlterminBase, EntityMitWurzelgebiet, WahlOderWahltermin {

  private static final long serialVersionUID = 1L;

  private static final Comparator<Wahl> WAHL_BY_POSITION_COMPARATOR = new WahlByPositionComparator();

  public AbstractWahltermin() {
    super();
  }

  @Override
  public int getWahljahr() {
    Calendar calendar = new GregorianCalendar();
    calendar.setTime(getWahldatum());

    return calendar.get(Calendar.YEAR);
  }

  @Override
  public String getWahlterminNummer() {
    return getNummer();
  }

  @Override
  public Gebiet getWurzelgebiet(EntityMitWurzelgebietDAO entityMitWurzelgebietDAO) {
    try {
      return entityMitWurzelgebietDAO.getWahlterminFct().apply((Wahltermin) this);
    } catch (NoResultException ignored) {
      return null;
    } catch (NonUniqueResultException e) {
      FacesMessageUtil.addErrorMessage("mehr.als.ein.wurzelgebiet.vorhanden");
      return null;
    }
  }

  public Date calculateStichtagVormWahltag(int anzahlTageVormWahltag) {
    return WahlterminStichtagCalculator.calculateTagVormWahltagByAnzahlTage((Wahltermin) this, anzahlTageVormWahltag);
  }

  public boolean isStichwahlMoeglich() {
    return Boolean.TRUE.equals(getStichwahlMoeglich());
  }

  public boolean isStichwahltermin() {
    return getStichwahlWahlterminUrspruenglich() != null;
  }

  // Nur für WOS(!)
  public boolean isWahlhelferdatenbank() {
    return "Wahlhelferdatenbank".equals(getName());
  }

  @Override
  public String getEinsehenRolleMessageKey() {
    return WahlterminConstants.MESSAGE_KEY_EINSEHEN_ID_EINZAHL;
  }

  public List<Wahl> getWahlenSortiertNachPosition() {
    return getWahlsByWahltermin().stream().sorted(WAHL_BY_POSITION_COMPARATOR).collect(Collectors.toList());
  }

  @Override
  public boolean isInstanceOfWahl() {
    return false;
  }

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

  @Override
  public EntityMitMandant getParent() {
    return getMandant();
  }

  /**
   * Identifikation des nicht festgelegten Wahldatums ist der 01.01. des Wahljahrs (WASDE-1904)
   */
  @Override
  public boolean isWahldatumNichtFestgelegt() {
    Calendar calendar = new GregorianCalendar();
    calendar.setTime(getWahldatum());
    return calendar.get(Calendar.DAY_OF_YEAR) == 1;
  }

  @Transient
  private transient WahlterminCreateDokumenteUebernehmen wahlterminCreateDokumenteUebernehmen;

  public WahlterminCreateDokumenteUebernehmen getWahlterminCreateDokumenteUebernehmen() {
    if (wahlterminCreateDokumenteUebernehmen == null) {
      return WahlterminCreateDokumenteUebernehmen.NICHT_UBERNEHMEN;
    }
    return wahlterminCreateDokumenteUebernehmen;
  }

  public void setWahlterminCreateDokumenteUebernehmen(WahlterminCreateDokumenteUebernehmen wahlterminCreateDokumenteUebernehmen) {
    this.wahlterminCreateDokumenteUebernehmen = wahlterminCreateDokumenteUebernehmen;
  }
}
