package de.ivu.elect.business.stimmeingabe.control.awerte;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

import javax.ejb.DependsOn;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.inject.Inject;

import de.ivu.elect.business.gebietsbaum.entity.GebietPK;
import de.ivu.elect.business.system.control.AbstractElectBackgroundService;
import de.ivu.elect.business.system.entity.SystemLogQuelle;

@Startup
@Singleton
@DependsOn("DbInit")
//https://issues.jboss.org/browse/EJBTHREE-2070 (keine Transaktion)
@TransactionManagement(TransactionManagementType.BEAN)
public class AWerteAusErgebniseingangUebernehmenBackgroundService extends AbstractElectBackgroundService {

  public static final AtomicLong RUNNING = createRunning();

  public static final AtomicBoolean DISABLED = createDisabled();

  private static final Map<GebietPK, AtomicLong> TODO = new ConcurrentHashMap<>();

  @Inject
  private transient AWerteAusErgebniseingangUebernehmen aWerteAusErgebniseingangUebernehmen;

  @Override
  protected AtomicBoolean getDisabledInternal() {
    return DISABLED;
  }

  @Override
  protected boolean isSomethingToDoInternal() {
    return getNextGebietPK() != null;
  }

  @Override
  protected void doSomethingInternal() {
    GebietPK nextGebietPK = getNextGebietPK();
    if (nextGebietPK != null) {
      aWerteAusErgebniseingangUebernehmen.uebernehmeAWerte(nextGebietPK);
      TODO.computeIfPresent(nextGebietPK, (x, y) -> {
        if (y.decrementAndGet() <= 0) {
          return null;
        }
        return y;
      });
    }
  }

  private GebietPK getNextGebietPK() {
    return TODO.entrySet().stream().filter(e -> e.getValue().get() > 0).map(Map.Entry::getKey).findAny().orElse(null);
  }

  public static void add(GebietPK gebietPK) {
    if (gebietPK != null) {
      long value = TODO.computeIfAbsent(gebietPK, x -> new AtomicLong(0L)).updateAndGet(o -> {
        if (o >= 1) {
          return 2L;
        }
        return 1L;
      });
    }
  }

  @Override
  public SystemLogQuelle getSystemLogQuelle() {
    return SystemLogQuelle.AWERTE_UEBERNEHMEN;
  }

  @Override
  protected AtomicLong getRunning() {
    return RUNNING;
  }
}
