
package de.ivu.elect.business.personenpruefung.control;

import static java.util.Arrays.asList;

import java.util.Collection;
import java.util.EnumSet;
import java.util.List;

import javax.annotation.Nullable;
import javax.inject.Inject;

import de.ivu.elect.business.person.boundary.PersonendatenDAO;
import de.ivu.elect.business.person.entity.Personendaten;
import de.ivu.elect.business.personenpruefung.entity.PersonenKonflikt;
import de.ivu.elect.business.personenpruefung.entity.PersonenKonfliktArt;
import de.ivu.elect.business.personenpruefung.entity.PersonenKonfliktStatus;

public class PersonenKonfliktCreate extends AbstractPersonenKonfliktCreate {

  @Inject
  private transient PersonendatenDAO personendatenDAO;

  public PersonenKonfliktCreate() {
    super();
  }

  private void removeByPersonAndKonfliktArt(Personendaten personendaten, Collection<PersonenKonfliktArt> personenKonfliktArten) {
    for (PersonenKonfliktArt personenKonfliktArt : personenKonfliktArten) {
      removeByPersonAndKonfliktArt(personendaten, personenKonfliktArt);
    }
  }

  public boolean removeByPersonAndKonfliktArt(Personendaten personendaten, PersonenKonfliktArt personenKonfliktArt) {
    PersonenKonflikt konflikt = findByPersonAndKonfliktArt(personendaten, personenKonfliktArt);

    if (konflikt == null) {
      return false;
    }

    dao.remove(konflikt);

    return true;
  }

  public PersonenKonflikt findOrCreate(Personendaten personendaten, PersonenKonfliktArt personenKonfliktArt, PersonenKonfliktStatus personenKonfliktStatus) {
    // NOTE ELECT-2773, dass beim Ablehnen einer Person alle anderen Konflikte zu löschen sind
    if (PersonenKonfliktStatus.IST_ABLEHNUNGSGRUND.equals(personenKonfliktStatus)) {
      removeByPersonAndKonfliktArt(personendaten, alleAusser(personenKonfliktArt));
    }

    PersonenKonflikt personenKonflikt = findByPersonAndKonfliktArt(personendaten, personenKonfliktArt);

    if (personenKonflikt == null) {
      return create(personendaten, personenKonfliktArt, personenKonfliktStatus);
    }

    if (!personenKonflikt.isKonfliktStatusIrrelevant()) {
      personenKonflikt.setPersonenKonfliktStatus(personenKonfliktStatus);
    }

    return personenKonflikt;
  }

  @Nullable
  private PersonenKonflikt findByPersonAndKonfliktArt(Personendaten personendaten, PersonenKonfliktArt personenKonfliktArt) {
    List<PersonenKonflikt> personenKonflikte = dao.findByPersonAndKonfliktArt(personendaten, asList(personenKonfliktArt));

    if (personenKonflikte.size() > 1) {
      throw new IllegalStateException(
          "Mehr als einen Konflikt fuer Person und KonfliktArt gefunden [personendaten = " + personendaten + ", konfliktArt = " + personenKonfliktArt + ", size = " + personenKonflikte.size() + "]");
    }

    if (!personenKonflikte.isEmpty()) {
      return personenKonflikte.get(0);
    }

    return null;
  }

  private PersonenKonflikt create(Personendaten personendaten, PersonenKonfliktArt personenKonfliktArt, PersonenKonfliktStatus personenKonfliktStatus) {
    PersonenKonflikt personenKonflikt = new PersonenKonflikt();
    personenKonflikt.setPersonendaten(personendatenDAO.attach(personendaten));
    personenKonflikt.setPersonenKonfliktArt(personenKonfliktArt);
    personenKonflikt.setPersonenKonfliktStatus(personenKonfliktStatus);

    save(personenKonflikt);

    return personenKonflikt;
  }

  private static Collection<PersonenKonfliktArt> alleAusser(PersonenKonfliktArt personenKonfliktArt) {
    return EnumSet.complementOf(EnumSet.of(personenKonfliktArt));
  }
}
