
package de.ivu.elect.business.wahlvorschlag.boundary;

import static java.util.stream.Collectors.toList;
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.apache.commons.lang3.StringUtils.leftPad;
import static org.apache.commons.lang3.StringUtils.replaceIgnoreCase;

import java.util.List;

import javax.ejb.Stateless;
import javax.inject.Inject;

import de.ivu.elect.business.gebietsbaum.boundary.WahldurchfuehrungsgebietDAO;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.gruppe.boundary.GruppeDAO;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.gruppe.entity.GruppeArt;
import de.ivu.elect.business.gruppe.entity.PolitischeGruppe;
import de.ivu.elect.business.gruppeimgebiet.boundary.GruppeImGebietDAO;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebietTK;
import de.ivu.elect.business.kandidatur.boundary.WaehlerBenannteKandidaturKonfiguration;
import de.ivu.elect.business.kandidatur.entity.Direktkandidatur;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahlvorschlag.control.WaehlerBenannteListeCreate;
import de.ivu.elect.business.wahlvorschlag.entity.Direktkandidat;
import de.ivu.elect.jee.faces.Messages;

@Stateless
public class WaehlerBenannterWahlvorschlagBoundaryCreate {

  @Inject
  private transient Messages messages;

  @Inject
  private transient GruppeDAO gruppeDAO;

  @Inject
  private transient WahldurchfuehrungsgebietDAO wahldurchfuehrungsgebietDAO;

  @Inject
  private transient GruppeImGebietDAO gruppeImGebietDAO;

  @Inject
  private transient WaehlerBenannteListeCreate waehlerBenannteListeCreate;

  @Inject
  private transient EinzelbewerberWahlvoschlagBoundaryCreate einzelbewerberWahlvoschlagBoundaryCreate;

  @Inject
  private transient WaehlerBenannteKandidaturKonfiguration waehlerBenannteKandidaturKonfiguration;

  public WaehlerBenannterWahlvorschlagBoundaryCreate() {
    super();
  }

  public void saveWaehlerBenannteListe(Gebiet gebiet) {
    Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = wahldurchfuehrungsgebietDAO.findByPrimaryKey(gebiet.getPk());

    if (wahldurchfuehrungsgebiet != null && wahldurchfuehrungsgebiet.isListenwahlgebiet()) {
      Wahl wahl = wahldurchfuehrungsgebiet.getWahl();

      PolitischeGruppe waehlerBenannteGruppe = waehlerBenannteListeCreate.findWaehlerBenannteListeGruppe(wahl);

      if (waehlerBenannteGruppe == null) {
        waehlerBenannteGruppe = waehlerBenannteListeCreate.createWaehlerBenannteListeGruppe(wahl);
      }

      waehlerBenannteListeCreate.createWaehlerBenannteListe(waehlerBenannteGruppe, wahldurchfuehrungsgebiet, GruppeImGebietTK.mappeGruppeImGebietNachTK(gruppeImGebietDAO.findByWahl(wahl)), true);
    }
  }

  public void saveWaehlerBenannterDirektkandidat(Direktkandidat direktkandidat) {
    Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = wahldurchfuehrungsgebietDAO.findByPrimaryKey(direktkandidat.getGebiet().getPk());

    if (wahldurchfuehrungsgebiet != null && wahldurchfuehrungsgebiet.isDirektwahlgebiet()) {
      Wahl wahl = wahldurchfuehrungsgebiet.getWahl();

      long kennwortIndex = generateWaehlerBenannterDirektkandidatKennwortIndex(wahl);

      String schluessel = generateWaehlerBenannterDirektkandidatSchluessel(kennwortIndex);
      String kennwort = defaultIfBlank(direktkandidat.getKennwort(), generateWaehlerBenannterDirektkandidatKennwort(kennwortIndex));
      String kurzname = defaultIfBlank(direktkandidat.getKurzname(), kennwort);

      direktkandidat.setKennwort(kennwort);
      direktkandidat.setKurzname(kurzname);
      direktkandidat.setWahlvorschlagStatus(WaehlerBenannteKandidaturKonfiguration.WAEHLER_BENANNTE_KANDIDATUR_WAHLVORSCHLAG_STATUS_DEFAULT);

      Direktkandidatur direktkandidatur = direktkandidat.getDirektkandidatur();
      direktkandidatur.setWahl(wahl);
      direktkandidatur.setKandidaturStatus(WaehlerBenannteKandidaturKonfiguration.WAEHLER_BENANNTE_KANDIDATUR_KANDIDATUR_STATUS_DEFAULT);

      PolitischeGruppe politischeGruppe = direktkandidatur.getGruppe();
      politischeGruppe.setWahl(wahl);
      politischeGruppe.setGruppeArt(GruppeArt.EINZELBEWERBER);
      politischeGruppe.setSchluessel(schluessel);
      politischeGruppe.setName(kennwort);
      politischeGruppe.setKurzname(kurzname);

      einzelbewerberWahlvoschlagBoundaryCreate.saveAndCreateEinzelkandidatur(direktkandidat, direktkandidatur);
    }
  }

  protected long generateWaehlerBenannterDirektkandidatKennwortIndex(Wahl wahl) {
    List<Gruppe> gruppen = gruppeDAO.findByWahl(wahl).stream() //
        .filter(waehlerBenannteKandidaturKonfiguration::isWaehlerBenannterDirektkandidatGruppe) //
        .collect(toList());

    return gruppen.stream() //
        .mapToLong(this::extractWaehlerBenannterDirektkandidatKennwortIndex) //
        .filter(kennwortIndex -> kennwortIndex > 0) //
        .map(kennwortIndex -> kennwortIndex + 1L) // Nächster Index...
        .max().orElse(gruppen.size() + 1L);
  }

  protected long extractWaehlerBenannterDirektkandidatKennwortIndex(Gruppe gruppe) {
    try {
      String schluesselKennwortIndex = replaceIgnoreCase(defaultIfBlank(gruppe.getSchluessel(), generateWaehlerBenannterDirektkandidatSchluessel(0)),
          WaehlerBenannteKandidaturKonfiguration.WAEHLER_BENANNTE_DIREKTKANDIDATUR_GRUPPE_SCHLUESSEL_PREFIX, "");

      return Long.parseLong(schluesselKennwortIndex);
    } catch (Exception ignored) {
    }

    return 0L;
  }

  protected String generateWaehlerBenannterDirektkandidatSchluessel(long kennwortIndex) {
    return WaehlerBenannteKandidaturKonfiguration.WAEHLER_BENANNTE_DIREKTKANDIDATUR_GRUPPE_SCHLUESSEL_PREFIX + leftPad("" + kennwortIndex, 3, "0");
  }

  public String generateWaehlerBenannterDirektkandidatKennwort(Wahl wahl) {
    return generateWaehlerBenannterDirektkandidatKennwort(generateWaehlerBenannterDirektkandidatKennwortIndex(wahl));
  }

  protected String generateWaehlerBenannterDirektkandidatKennwort(long kennwortIndex) {
    return getMessage(WaehlerBenannteKandidaturKonfiguration.MSG_KEY_WAEHLER_BENANNTE_DIREKTKANDIDATUR_KENNWORT_DEFAULT, kennwortIndex);
  }

  private String getMessage(String msgKey, Object... params) {
    return messages.getMessageForMessageKey(msgKey, params);
  }
}
