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

import static com.querydsl.core.types.dsl.Expressions.anyOf;

import java.io.Serializable;
import java.util.List;

import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.enterprise.event.Observes;
import javax.enterprise.event.Reception;
import javax.enterprise.event.TransactionPhase;
import javax.inject.Inject;

import com.querydsl.jpa.impl.JPAQuery;

import de.ivu.elect.business.person.entity.AbstractPersonendaten;
import de.ivu.elect.business.person.entity.Personendaten;
import de.ivu.elect.business.person.entity.QPersonendaten;
import de.ivu.elect.business.personenpruefung.boundary.PersonenKonfliktEdit;
import de.ivu.elect.business.personenpruefung.boundary.PersonenPruefungStarter;

@Stateless
public class PersonenKonfliktZuruecksetzerOnBerufUpdateEvent implements Serializable {

  private static final long serialVersionUID = 1L;

  protected static final String ATTRIBUTE_AS_LIST_SEPARATOR = AbstractPersonendaten.ATTRIBUTE_AS_LIST_SEPARATOR;

  @Inject
  PersonenKonfliktEdit personenKonfliktEdit;

  @Inject
  PersonenPruefungStarter personenPruefungStarter;

  @Inject
  PersonendatenDAO personendatenDAO;

  @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
  public void listen(
      @Observes(during = TransactionPhase.AFTER_SUCCESS, notifyObserver = Reception.ALWAYS) BerufUpdatedEvent event) {

    if (event.getOldValue() == null) {
      if (event.getNewValue() == null) {
        return; // Event ohne veränderte Werte nichts zu tun
      }
      // Wert wurde angelegt
      postBerufCreate(event.getNewValue());

    } else if (event.getNewValue() == null) {
      // Wert wurde gelöscht
      postBerufDelete(event.getOldValue());

    } else {
      // Wert wurde umbenannt
      postBerufChange(event.getOldValue(), event.getNewValue());

    }

    // Starte Prüfung
    personenPruefungStarter.startePersonenPruefung();
  }

  private void postBerufChange(String oldValue, String newValue) {
    if (!newValue.equals(oldValue)) {
      postBerufDelete(oldValue);
      postBerufCreate(newValue);
    }
  }

  private void postBerufCreate(String newValue) {
    List< ? extends Personendaten> personenMitNeuemBeruf = findePersonenMitBeruf(newValue);
    personenKonfliktEdit.resetPersonenKonfliktWertelistenAbgleichManuellZuPruefen(personenMitNeuemBeruf);
  }

  private void postBerufDelete(String oldValue) {
    List< ? extends Personendaten> personenMitAltemWert = findePersonenMitBeruf(oldValue);
    personenKonfliktEdit.deletePersonenKonfliktWertelistenAbgleichAndSetPersonStatusUngeprueft(personenMitAltemWert);
  }

  protected List< ? extends Personendaten> findePersonenMitBeruf(String beruf) {
    QPersonendaten personendatenTable = QPersonendaten.personendaten;
    JPAQuery query = personendatenDAO.getQueryDsl().from(personendatenTable).getQuery();

    query.where(anyOf(personendatenTable.berufUnformatiert.eq(beruf),
        personendatenTable.berufUnformatiert.startsWith(beruf + ATTRIBUTE_AS_LIST_SEPARATOR),
        personendatenTable.berufUnformatiert.endsWith(ATTRIBUTE_AS_LIST_SEPARATOR + beruf),
        personendatenTable.berufUnformatiert.like(ATTRIBUTE_AS_LIST_SEPARATOR + beruf + ATTRIBUTE_AS_LIST_SEPARATOR)));

    return query.fetch();
  }
}
