// 
// Decompiled by Procyon v0.6.0
// 

package com.nimbusds.jose.jwk.source;

import com.nimbusds.jose.KeySourceException;
import com.nimbusds.jose.util.events.Event;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.util.events.EventListener;
import com.nimbusds.jose.shaded.jcip.ThreadSafe;
import com.nimbusds.jose.proc.SecurityContext;

@ThreadSafe
public class RateLimitedJWKSetSource<C extends SecurityContext> extends JWKSetSourceWrapper<C>
{
    private final long minTimeInterval;
    private long nextOpeningTime;
    private int counter;
    private final EventListener<RateLimitedJWKSetSource<C>, C> eventListener;
    
    public RateLimitedJWKSetSource(final JWKSetSource<C> source, final long minTimeInterval, final EventListener<RateLimitedJWKSetSource<C>, C> eventListener) {
        super(source);
        this.nextOpeningTime = -1L;
        this.counter = 0;
        this.minTimeInterval = minTimeInterval;
        this.eventListener = eventListener;
    }
    
    @Override
    public JWKSet getJWKSet(final JWKSetCacheRefreshEvaluator refreshEvaluator, final long currentTime, final C context) throws KeySourceException {
        boolean rateLimitHit;
        synchronized (this) {
            if (this.nextOpeningTime <= currentTime) {
                this.nextOpeningTime = currentTime + this.minTimeInterval;
                this.counter = 1;
                rateLimitHit = false;
            }
            else {
                rateLimitHit = (this.counter <= 0);
                if (!rateLimitHit) {
                    --this.counter;
                }
            }
        }
        if (rateLimitHit) {
            if (this.eventListener != null) {
                this.eventListener.notify((Event<RateLimitedJWKSetSource<C>, C>)new RateLimitedEvent(this, (SecurityContext)context));
            }
            throw new RateLimitReachedException();
        }
        return this.getSource().getJWKSet(refreshEvaluator, currentTime, context);
    }
    
    public long getMinTimeInterval() {
        return this.minTimeInterval;
    }
    
    public static class RateLimitedEvent<C extends SecurityContext> extends AbstractJWKSetSourceEvent<RateLimitedJWKSetSource<C>, C>
    {
        private RateLimitedEvent(final RateLimitedJWKSetSource<C> source, final C securityContext) {
            super(source, securityContext);
        }
    }
}
