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

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

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

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gruppe.boundary.GruppeDAO;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.gruppe.entity.PolitischeGruppe;
import de.ivu.elect.business.gruppeimgebiet.boundary.GruppeImGebietDAO;
import de.ivu.elect.business.gruppeimgebiet.boundary.GruppeImGebietFactory;
import de.ivu.elect.business.gruppeimgebiet.boundary.GruppeImGebietHierarchyBuilder;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebiet;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebietTK;
import de.ivu.elect.business.wahlvorschlag.entity.Direktkandidat;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.business.wahlvorschlag.entity.Wahlvorschlag;
import de.ivu.elect.business.wahlvorschlag.entity.WahlvorschlagStatus;
import de.ivu.elect.business.wahlvorschlagsperson.boundary.WahlvorschlagsPersonDAO;
import de.ivu.elect.business.wahlvorschlagsperson.boundary.WahlvorschlagsPersonEdit;
import de.ivu.elect.business.wahlvorschlagsperson.entity.WahlvorschlagsPerson;

@Stateless
public class WahlvorschlagCommonEdit {

  private static final Logger LOG = LoggerFactory.getLogger(WahlvorschlagCommonEdit.class);

  @Inject
  private transient ListeDAO listeDAO;

  @Inject
  private transient DirektkandidatDAO direktkandidatDAO;

  @Inject
  private transient WahlvorschlagsPersonDAO wahlvorschlagsPersonDAO;

  @Inject
  private transient WahlvorschlagsPersonEdit wahlvorschlagsPersonEdit;

  @Inject
  private transient GruppeImGebietHierarchyBuilder gruppeImGebietHierarchyBuilder;

  @Inject
  private transient GruppeImGebietDAO gruppeImGebietDAO;

  @Inject
  private transient GruppeImGebietFactory gruppeImGebietFactory;

  @Inject
  private transient WahlvorschlagDAO wahlvorschlagDAO;

  @Inject
  private transient GruppeDAO gruppeDAO;

  public WahlvorschlagCommonEdit() {
    super();
  }

  public void setStatus(Liste template, WahlvorschlagStatus wahlvorschlagStatus) {
    Map<String, Object> tmp = template.getTransientContext();
    Liste attached = listeDAO.attach(template);
    attached.getTransientContext().putAll(tmp);
    setStatusInternal(attached, wahlvorschlagStatus);
  }

  protected void setStatusInternal(Liste liste, WahlvorschlagStatus wahlvorschlagStatus) {
    liste.setWahlvorschlagStatus(wahlvorschlagStatus);
  }

  public void setStatus(Direktkandidat template, WahlvorschlagStatus wahlvorschlagStatus) {
    direktkandidatDAO.attach(template).setWahlvorschlagStatus(wahlvorschlagStatus);
  }

  public void updateGruppeImGebietPreSave(Wahlvorschlag wahlvorschlag, GruppeImGebiet gruppeImGebiet) {
    gruppeImGebietHierarchyBuilder.updateGruppeImGebietNamen(gruppeImGebiet, wahlvorschlag);
    gruppeImGebietHierarchyBuilder.saveAndCompleteHierarchy(gruppeImGebiet);
  }

  public void updateGruppeImGebietPreDelete(Wahlvorschlag wahlvorschlag, GruppeImGebiet gruppeImGebiet) {
    if (wahlvorschlag != null) {
      wahlvorschlag.setGruppeImGebiet(null);
      wahlvorschlag.setGruppeImGebietOhneUpdateBeziehung(gruppeImGebiet);
    }
  }

  public void updateGruppeImGebietPostDelete(GruppeImGebiet gruppeImGebiet) {
    if (gruppeImGebiet != null) {
      gruppeImGebiet.setRelativePosition(null);
      gruppeImGebiet.setVorgegebenePosition(null);
    }
  }

  public void deleteWahlvorschlagsPersonen(Wahlvorschlag wahlvorschlag) {
    if (wahlvorschlag != null) {
      for (WahlvorschlagsPerson wahlvorschlagsPerson : wahlvorschlagsPersonDAO.findByWahlvorschlag(wahlvorschlag)) {
        wahlvorschlagsPersonEdit.delete(wahlvorschlagsPerson);
      }
    }
  }

  public void gruppeWechseln(Wahlvorschlag wahlvorschlagNotAttached, PolitischeGruppe neueGruppeNotAttached) {
    if (wahlvorschlagNotAttached == null || neueGruppeNotAttached == null) {
      return;
    }

    Wahlvorschlag wahlvorschlag = wahlvorschlagDAO.attach(wahlvorschlagNotAttached);
    Gruppe neueGruppe = gruppeDAO.attach(neueGruppeNotAttached);
    if (neueGruppe.equals(wahlvorschlag.getGruppe())) {
      return;
    }

    Gebiet gebiet = wahlvorschlag.getGebiet();
    LOG.info("Gruppe wechseln: wahlvorschlag=" + wahlvorschlag + ", neueGruppe=" + neueGruppe + ", gebiet=" + gebiet);

    List<GruppeImGebiet> gigDerGruppe = gruppeImGebietDAO.findByGruppe(neueGruppe);

    Map<GruppeImGebietTK, GruppeImGebiet> gigNachTk = gigDerGruppe.stream()
        .collect(Collectors.toMap(GruppeImGebiet::getGruppeImGebietTK, gruppeImGebiet -> gruppeImGebiet, (a, b) -> b));

    GruppeImGebiet gigImGebiet = gigNachTk.get(new GruppeImGebietTK(gebiet.getGebietTK(), neueGruppe.getGruppeTK()));

    if (gigImGebiet == null) {
      LOG.info("Gruppe wechseln: gigImGebiet neu anlegen");
      gigImGebiet = gruppeImGebietFactory.create();
      gigImGebiet.setGruppe(neueGruppe);
      gigImGebiet.setGebiet(gebiet);
      gruppeImGebietDAO.persist(gigImGebiet);
      gigNachTk.put(gigImGebiet.getGruppeImGebietTK(), gigImGebiet);
      // ELECT-11011 gruppeImGebietHierarchyBuilder.updateGruppeImGebietNamen(gigImGebiet, wahlvorschlag);
    }

    LOG.info("Gruppe wechseln: gigImGebiet=" + gigImGebiet);

    gruppeImGebietHierarchyBuilder.saveAndCompleteHierarchy(gigImGebiet, gigNachTk);

    for (GruppeImGebiet gruppeImGebiet : gigDerGruppe) {
      // ELECT-11013
      if (gruppeImGebiet.getGebiet().isInGebietshierarchieUntergeordnetesGebietVon(gebiet)) {
        gruppeImGebiet.setName(null);
        gruppeImGebiet.setKurzname(null);
        gruppeImGebiet.setVorgegebenePosition(null);
      }
    }

    wahlvorschlag.setGruppeImGebiet(gigImGebiet);

    // WASDE-2071 Namen der Gruppe in Wahlvorschlag übernehmen
    String kennwortNeu = StringUtils.defaultString(gigImGebiet.getName(), neueGruppe.getName());
    String kurznameNeu = StringUtils.defaultString(gigImGebiet.getKurzname(), neueGruppe.getKurzname());
    String zusatzbezeichnungNeu = StringUtils.defaultString(gigImGebiet.getZusatzbezeichnung(), neueGruppe.getZusatzbezeichnung());
    LOG.info("Gruppe wechseln: wahlvorschlagKennwortAlt=" + wahlvorschlag.getKennwort() + ", wahlvorschlagKennwortNeu=" + kennwortNeu
        + ", wahlvorschlagKurznameAlt=" + wahlvorschlag.getKurzname() + ", wahlvorschlagKurznameNeu=" + kurznameNeu
        + ", wahlvorschlagZusatzbezeichnungAlt=" + wahlvorschlag.getZusatzbezeichnung() + ", wahlvorschlagZusatzbezeichnungNeu=" + zusatzbezeichnungNeu);
    wahlvorschlag.setKennwort(kennwortNeu);
    wahlvorschlag.setKurzname(kurznameNeu);
    wahlvorschlag.setZusatzbezeichnung(zusatzbezeichnungNeu);
    wahlvorschlagNotAttached.setKennwort(kennwortNeu);
    wahlvorschlagNotAttached.setKurzname(kurznameNeu);
    wahlvorschlagNotAttached.setZusatzbezeichnung(zusatzbezeichnungNeu);
  }
}
