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

import java.util.Collection;

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

import de.ivu.elect.business.person.boundary.PersonenVerknuepfungDAO;
import de.ivu.elect.business.person.entity.PersonenVerknuepfung;
import de.ivu.elect.business.personenpruefung.boundary.PersonenKonfliktDAO;
import de.ivu.elect.business.personenpruefung.entity.PersonenKonflikt;
import de.ivu.elect.business.personenpruefung.entity.PersonenKonfliktArt;
import de.ivu.elect.business.personenpruefung.entity.PersonenKonfliktStatus;
import de.ivu.elect.business.wahlvorschlagsperson.control.WahlvorschlagsPersonCreate;
import de.ivu.elect.business.wahlvorschlagsperson.control.WahlvorschlagsPersonPoolPersonendatenMapper;
import de.ivu.elect.business.wahlvorschlagsperson.entity.WahlvorschlagsPerson;


import static java.util.Arrays.asList;

@Stateless
public class WahlvorschlagsPersonPoolCreate {

  @Inject
  protected transient WahlvorschlagsPersonDAO wahlvorschlagsPersonDao;

  @Inject
  protected transient PersonenVerknuepfungDAO personenVerknuepfungDao;

  @Inject
  protected transient PersonenKonfliktDAO personenKonfliktDao;

  @Inject
  protected transient WahlvorschlagsPersonCreate wahlvorschlagsPersonCreate;

  @Inject
  protected transient WahlvorschlagsPersonPoolPersonendatenMapper wahlvorschlagsPersonPoolPersonendatenMapper;

  @Inject
  protected transient WahlvorschlagsPersonPoolPersonenVerknuepfungResolver wahlvorschlagsPersonPoolPersonenVerknuepfungResolver;

  public WahlvorschlagsPersonPoolCreate() {
    super();
  }

  public void create(WahlvorschlagsPerson wahlvorschlagsPerson, WahlvorschlagsPerson template) {
    createIncludingPersonenVerknuepfungenAndPersonenKonflikte(wahlvorschlagsPerson, wahlvorschlagsPersonDao.attach(template));
  }

  protected void createIncludingPersonenVerknuepfungenAndPersonenKonflikte(WahlvorschlagsPerson wahlvorschlagsPerson,
      WahlvorschlagsPerson template) {
    // NOTE, dass die NEUE WahlvorschlagsPerson in der Oberfläche momentan 'readonly' angezeigt wird und beim Anlegen
    // NICHT EDITIERT WERDEN KANN. Sollte sich dies ändern, müssen evtl. Änderungen an den ursprünglichen Personendaten
    // auch an jeder Kopie vorgenommen werden und ABSCHLIESSEND die Personenprüfung gestartet werden!
    wahlvorschlagsPersonPoolPersonendatenMapper.map(wahlvorschlagsPerson, template);

    wahlvorschlagsPersonCreate.saveExcludingPersonenPruefung(wahlvorschlagsPerson);

    // NOTE, dass die NEUE WahlvorschlagsPerson mit ALLEN bereits bekannten Kopien verknüpft wird!
    for (WahlvorschlagsPerson wahlvorschlagsPersonVerknuepft : getWahlvorschlagsPersonenVerknuepft(template)) {
      personenVerknuepfungDao.persist(createPersonenVerknuepfung(wahlvorschlagsPerson, wahlvorschlagsPersonVerknuepft));
    }

    for (PersonenKonflikt personenKonflikt : getPersonenKonflikte(template)) {
      personenKonfliktDao.persist(createPersonenKonflikt(wahlvorschlagsPerson, personenKonflikt.getPersonenKonfliktArt(),
          personenKonflikt.getPersonenKonfliktStatus()));
    }
  }

  private PersonenVerknuepfung createPersonenVerknuepfung(WahlvorschlagsPerson wahlvorschlagsPerson,
      WahlvorschlagsPerson wahlvorschlagsPersonVerknuepft) {
    return wahlvorschlagsPersonPoolPersonenVerknuepfungResolver.createWahlvorschlagsPersonPoolPersonenVerknuepfung(wahlvorschlagsPerson,
        wahlvorschlagsPersonVerknuepft);
  }

  private Collection<WahlvorschlagsPerson> getWahlvorschlagsPersonenVerknuepft(WahlvorschlagsPerson wahlvorschlagsPerson) {
    return wahlvorschlagsPersonPoolPersonenVerknuepfungResolver.getWahlvorschlagsPersonenVerknuepft(wahlvorschlagsPerson);
  }

  private PersonenKonflikt createPersonenKonflikt(WahlvorschlagsPerson wahlvorschlagsPerson, PersonenKonfliktArt personenKonfliktArt,
      PersonenKonfliktStatus personenKonfliktStatus) {
    PersonenKonflikt personenKonflikt = new PersonenKonflikt();
    personenKonflikt.setPersonendaten(wahlvorschlagsPerson);
    personenKonflikt.setPersonenKonfliktArt(personenKonfliktArt);
    personenKonflikt.setPersonenKonfliktStatus(personenKonfliktStatus);

    return personenKonflikt;
  }

  private Collection<PersonenKonflikt> getPersonenKonflikte(WahlvorschlagsPerson wahlvorschlagsPerson) {
    return personenKonfliktDao.findByPersonAndKonfliktArt(wahlvorschlagsPerson, asList(PersonenKonfliktArt.values()));
  }
}
