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

import static java.util.Arrays.asList;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

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 PersonendatenDAO personendatenDao;

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

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

    if (konflikt == null) {
      return false;
    }
    dao.remove(konflikt);
    return true;
  }

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

    PersonenKonflikt konflikt = findByPersonAndKonfliktArt(personendaten, konfliktArt);

    if (konflikt == null) {
      return create(personendaten, konfliktArt, konfliktStatus);
    }

    // TODO: Sicher, dass irrelevante Konflikte hier nicht überschrieben werden sollen?
    if (!konflikt.isKonfliktStatusIrrelevant()) {
      konflikt.setPersonenKonfliktStatus(konfliktStatus);
    }

    return konflikt;
  }

  private PersonenKonflikt findByPersonAndKonfliktArt(Personendaten personendaten, PersonenKonfliktArt konfliktArt) {
    List<PersonenKonflikt> konflikte = dao.findByPersonAndKonfliktArt(personendaten, asList(konfliktArt));

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

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

    return null;
  }

  private PersonenKonflikt create(Personendaten personendaten, PersonenKonfliktArt konfliktArt,
      PersonenKonfliktStatus konfliktStatus) {
    PersonenKonflikt konflikt = new PersonenKonflikt();

    konflikt.setPersonendaten(personendatenDao.attach(personendaten));
    konflikt.setPersonenKonfliktArt(konfliktArt);
    konflikt.setPersonenKonfliktStatus(konfliktStatus);

    save(konflikt);

    return konflikt;
  }

  private static Collection<PersonenKonfliktArt> alleAusser(PersonenKonfliktArt personenKonfliktArt) {
    ArrayList<PersonenKonfliktArt> result = new ArrayList<>(asList(PersonenKonfliktArt.values()));

    result.remove(personenKonfliktArt);

    return result;
  }
}
