import clock.io.ClockOutput;
import java.util.concurrent.Semaphore;

class Monitor {
    private NaiveTime currentTime = new NaiveTime();
    private NaiveTime alarmTime = new NaiveTime();

    private boolean alarm = false;
    private int beepCount = 0;

    private Semaphore sema = new Semaphore(1);
    private ClockOutput out;

    Monitor(ClockOutput out) {
        this.out = out;
    }

    Monitor(int h, int m, int s, ClockOutput out) {
        currentTime = new NaiveTime(h, m, s);
        this.out = out;
    }

    void setTime(int h, int m, int s) throws InterruptedException {
        sema.acquire();
        currentTime.set(h, m, s);
        sema.release();
    }

    void setAlarm(int h, int m, int s) throws InterruptedException {
        sema.acquire();
        alarmTime = new NaiveTime(h, m, s);
        sema.release();
    }

    void setAlarm(boolean on) {
        alarm = on;
    }

    boolean getAlarmStatus() {
        return this.alarm;
    }

    void toggleAlarm() {
        alarm = !alarm;
    }

    NaiveTime getTime() {
        return currentTime;
    }

    void tick() throws InterruptedException {
        sema.acquire();
        currentTime.tick();

        if (currentTime.equals(alarmTime) && beepCount == 0) {
            triggerAlarm();
        }

        // Decrement beep count each tick
        if (beepCount > 0)
            beepCount--;

        // Stop alarm when count hits zero
        if (beepCount == 0 && alarm)
            stopAlarm();

        sema.release();
    }

    void triggerAlarm() {
        System.out.println("Alarm triggered!");
        beepCount = 5;
        this.setAlarm(true);
        out.setAlarmIndicator(true);
    }

    void stopAlarm() {
        System.out.println("Alarm stopped after 5 beeps.");
        this.setAlarm(false);
        out.setAlarmIndicator(false);
    }
}
