package org.springblade.modules.nh.factory.common;

import java.util.*;

public class TimeWindow {

    private final Queue<WindowEntry> entries;
    private final long cap;
    private long size;

    /**
     * @param duration unit: ms
     * @param cap      capacity
     */
    public TimeWindow(int duration, int cap) {
        this.cap = cap;
        this.size = 0;
        this.entries = new PriorityQueue<>(cap, new Comparator<WindowEntry>() {
            @Override
            public int compare(WindowEntry o1, WindowEntry o2) {
                return Long.compare(o1.getT(), o2.getT());
            }
        });
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                long old = System.currentTimeMillis() - duration;
                int v = 0;
                synchronized (TimeWindow.this) {
                    while (true) {
                        WindowEntry en = entries.peek();
                        if (en == null || en.getT() > old) {
                            break;
                        }
                        entries.poll();
                        v++;
                    }
                    if (v > 0) {
                        size = size - v;
                        assert size >= 0;
                        TimeWindow.this.notifyAll();
                    }
                }
            }
        }, 1000, 1000);
    }

    public synchronized void add() {
        while (true) {
            if (size >= cap) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    // ignore
                }
            } else {
                this.size++;
                this.entries.add(new WindowEntry(System.currentTimeMillis()));
                break;
            }
        }
    }

}
