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

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;

import javax.enterprise.event.Observes;
import javax.enterprise.event.Reception;
import javax.inject.Inject;

import org.apache.deltaspike.core.api.scope.ConversationGroup;
import org.apache.deltaspike.core.api.scope.GroupedConversation;
import org.apache.deltaspike.core.api.scope.GroupedConversationScoped;

import de.ivu.elect.business.entschaedigung.entity.Entschaedigung;
import de.ivu.elect.business.entschaedigung.entity.Entschaedigungsart;
import de.ivu.elect.business.wahl.boundary.WahlSelectChangeEvent;
import de.ivu.elect.business.wahl.boundary.WahlterminSelectChangeEvent;

@GroupedConversationScoped
@ConversationGroup(EntschaedigungBulkEditConversationStore.class)
public class EntschaedigungBulkEditConversationStore implements Serializable {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient GroupedConversation groupedConversation;

  // NOTE, dass eine Map verwendet wird, da Entschädigungen ggf. live berechnet sind. Das heißt insbesondere, dass nicht garantiert ist,
  // dass jede Entschädigung eine ID besitzt! Die Entschädigungsart hingegen muss bereits persistiert sein.
  private final SortedMap<Long, Entschaedigung> entschaedigungPerEntschaedigungsartId;

  public EntschaedigungBulkEditConversationStore() {
    super();

    this.entschaedigungPerEntschaedigungsartId = new TreeMap<>();
  }

  public void onWahlSelectChangeEvent(@Observes(notifyObserver = Reception.IF_EXISTS) WahlSelectChangeEvent event) {
    close();
  }

  public void onWahlterminSelectChangeEvent(@Observes(notifyObserver = Reception.IF_EXISTS) WahlterminSelectChangeEvent event) {
    close();
  }

  public List<Entschaedigung> addEntschaedigungen(List<Entschaedigung> entschaedigungen) {
    Collection<Long> entschaedigungsartIds = new HashSet<>();

    entschaedigungen.forEach(entschaedigung -> {
      Entschaedigungsart entschaedigungsart = entschaedigung.getEntschaedigungsart();

      if (entschaedigungsart != null) {
        Long entschaedigungsartId = entschaedigungsart.getId();
        entschaedigungsartIds.add(entschaedigungsartId);

        entschaedigungPerEntschaedigungsartId.put(entschaedigungsartId, entschaedigung);
      }
    });

    return collectEntschaedigungen(entschaedigungsartIds);
  }

  public List<Entschaedigung> getEntschaedigungen() {
    return collectEntschaedigungen(entschaedigungPerEntschaedigungsartId.keySet());
  }

  private List<Entschaedigung> collectEntschaedigungen(Collection<Long> entschaedigungsartIds) {
    List<Entschaedigung> result = new ArrayList<>();

    for (Long entschaedigungsartId : new TreeSet<>(entschaedigungsartIds)) {
      result.add(entschaedigungPerEntschaedigungsartId.get(entschaedigungsartId));
    }

    return result;
  }

  public void close() {
    entschaedigungPerEntschaedigungsartId.clear();

    groupedConversation.close();
  }
}
