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

import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

import javax.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.benutzerverwaltung.entity.AbstractBenutzer;
import de.ivu.elect.business.benutzerverwaltung.entity.Benutzer;
import de.ivu.elect.business.benutzerverwaltung.entity.BenutzerPK;
import de.ivu.elect.business.konfiguration.entity.ElectKonfigurationWerte;
import de.ivu.elect.business.konfiguration.entity.KonfigurationLoader;
import de.ivu.elect.business.system.boundary.SystemLogWriter;
import de.ivu.elect.business.system.entity.SystemLogQuelle;
import de.ivu.elect.jee.faces.Messages;

public class DatabaseLoginServiceHelper implements Serializable {

  private static final long serialVersionUID = 1L;

  private static final Logger LOG = LoggerFactory.getLogger(DatabaseLoginServiceHelper.class);

  protected static final long ONE_MINUTE_IN_MS = TimeUnit.MINUTES.toMillis(1);

  @Inject
  private transient SystemLogWriter systemLogWriter;

  @Inject
  private transient Messages messages;

  @Inject
  private transient KonfigurationLoader konfigurationLoader;

  private static final Map<BenutzerPK, AtomicLong> ADMIN_VERSUCHE = new ConcurrentHashMap<>();

  /*
   * ELECTVAPP-358
   */
  public boolean sonderbehandlungAdmin(Benutzer benutzer) {
    if (konfigurationLoader.resolveBooleanValue(ElectKonfigurationWerte.LOGIN_SERVICE_ADMIN_SPERREN)) {
      if (benutzer.getLoginVersuche() >= AbstractBenutzer.ACCOUNT_GESPERRT_AB_LOGIN_VERSUCHE) {
        long differenz = (getAdminVersuch(benutzer.getPk()).get() + ONE_MINUTE_IN_MS) - System.currentTimeMillis();
        if (differenz > 0) {
          systemLogWriter.writeErrorLogMessageFuerMandant(benutzer.getMandant(),
              messages.getMessageForMessageKey("admin.nutzer.zu.viele.fehlversuche", benutzer.getBenutzerkennung()), SystemLogQuelle.SYSTEM);

          if (!benutzer.getMandant().getArt().isSystemMandant()) {
            systemLogWriter.writeErrorLogMessageFuerSystemMandant(
                messages.getMessageForMessageKey("admin.nutzer.zu.viele.fehlversuche.system", benutzer.getBenutzerkennung(),
                    benutzer.getMandant().getNummer(), benutzer.getMandant().getName()),
                SystemLogQuelle.SYSTEM);
          }

          LOG.warn("Admin noch gesperrt: " + differenz);
          return true;
        }
      }
      getAdminVersuch(benutzer.getPk()).set(System.currentTimeMillis());
    }
    return false;
  }

  private AtomicLong getAdminVersuch(BenutzerPK pk) {
    if (pk == null) {
      return new AtomicLong(0);
    }

    return ADMIN_VERSUCHE.computeIfAbsent(pk, x -> new AtomicLong(0));
  }

}
