package de.ivu.elect.jee.doubleclick;

import java.io.Serializable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;

import de.ivu.elect.jee.exception.ElectCommonException;

@Interceptor
@PreventDoubleClick
public class PreventDoubleClickInterceptor implements Serializable {

  private static final long serialVersionUID = 1L;

  @AroundInvoke
  public Object secure(InvocationContext ctx) throws Exception {
    PreventDoubleClickLockProvider lockProvider = (PreventDoubleClickLockProvider) ctx.getTarget();

    ReentrantLock lock = lockProvider.getLock();

    if (lock.tryLock(60, TimeUnit.SECONDS)) { // TODO Zeit an Annotation konfigurierbar machen
      try {
        return ctx.proceed();
      } finally {
        lock.unlock();
      }
    }
    throw new ElectCommonException(ElectCommonException.RedirectDestination.ERROR_VIEW, "prevent.double.click.listener", tryGetTarget(ctx), tryGetMethod(ctx), tryGetName(lockProvider), tryGetLogMessageContext(lockProvider));
  }

  private String tryGetLogMessageContext(PreventDoubleClickLockProvider lockProvider) {
    try {
      return lockProvider.getLogMessageContext();
    } catch (Exception e) {
      return "e=" + e.getMessage();
    }
  }

  private String tryGetName(PreventDoubleClickLockProvider lockProvider) {
    try {
      return lockProvider.getName();
    } catch (Exception e) {
      return "e=" + e.getMessage();
    }
  }

  private String tryGetMethod(InvocationContext ctx) {
    try {
      return ctx.getMethod().getName();
    } catch (Exception e) {
      return "e=" + e.getMessage();
    }
  }

  private String tryGetTarget(InvocationContext ctx) {
    try {
      return ctx.getTarget().getClass().getName();
    } catch (Exception e) {
      return "e=" + e.getMessage();
    }
  }
}
