package com.ycwl.basic.utils.ratelimiter;

import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class FixedRateLimiter implements IRateLimiter {
    private final Semaphore semaphore = new Semaphore(1);
    private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);

    public FixedRateLimiter(float maxRequestsPerSecond) {
        semaphore.tryAcquire();
        int rate = Float.valueOf(1000 / maxRequestsPerSecond).intValue();
        scheduler.scheduleAtFixedRate(() -> {
            if (semaphore.availablePermits() < 1) {
                semaphore.release(1);
            }
        }, rate, rate, TimeUnit.MILLISECONDS);
    }


    public FixedRateLimiter(int rate, TimeUnit timeUnit) {
        semaphore.tryAcquire();
        scheduler.scheduleAtFixedRate(() -> {
            if (semaphore.availablePermits() < 1) {
                semaphore.release(1);
            }
        }, rate, rate, timeUnit);
    }

    @Override
    public void acquire() throws InterruptedException {
        semaphore.acquire();
    }

    @Override
    public void shutdown() {
        scheduler.shutdown();
    }

    @Override
    public boolean tryAcquire() {
        return semaphore.tryAcquire();
    }

    @Override
    public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException {
        return semaphore.tryAcquire(timeout, unit);
    }
}
