"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Alarm_1 = require("../models/Alarm");
const Note_1 = require("../models/Note");
class AlarmService {
    // private static inAppNotificationHandler_:any;
    // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
    static setDriver(v) {
        this.driver_ = v;
        if (this.driver_.setService)
            this.driver_.setService(this);
    }
    static driver() {
        if (!this.driver_)
            throw new Error('AlarmService driver not set!');
        return this.driver_;
    }
    static setLogger(v) {
        this.logger_ = v;
    }
    static logger() {
        return this.logger_;
    }
    // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
    static setInAppNotificationHandler(v) {
        // this.inAppNotificationHandler_ = v;
        if (this.driver_.setInAppNotificationHandler)
            this.driver_.setInAppNotificationHandler(v);
    }
    static async garbageCollect() {
        this.logger().info('Garbage collecting alarms...');
        // Delete alarms that have already been triggered
        await Alarm_1.default.deleteExpiredAlarms();
        // Delete alarms that correspond to non-existent notes
        const alarmIds = await Alarm_1.default.alarmIdsWithoutNotes();
        for (let i = 0; i < alarmIds.length; i++) {
            this.logger().info(`Clearing notification for non-existing note. Alarm ${alarmIds[i]}`);
            await this.driver().clearNotification(alarmIds[i]);
        }
        await Alarm_1.default.batchDelete(alarmIds, { sourceDescription: 'AlarmService/garbageCollect' });
    }
    // When passing a note, make sure it has all the required properties
    // (better to pass a complete note or else just the ID)
    // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
    static async updateNoteNotification(noteOrId, isDeleted = false) {
        try {
            let note = null;
            let noteId = null;
            if (typeof noteOrId === 'object') {
                note = noteOrId;
                noteId = note.id;
            }
            else {
                note = await Note_1.default.load(noteOrId);
                noteId = note ? note.id : null;
            }
            if (!note && !isDeleted)
                return;
            const driver = this.driver();
            let alarm = noteId ? await Alarm_1.default.byNoteId(noteId) : null;
            let clearAlarm = false;
            if (isDeleted || !Note_1.default.needAlarm(note) || (alarm && alarm.trigger_time !== note.todo_due)) {
                clearAlarm = !!alarm;
            }
            if (!clearAlarm && alarm) {
                // Alarm already exists and set at the right time
                // For persistent notifications (those that stay active after the app has been closed, like on mobile), if we have
                // an alarm object we can be sure that the notification has already been set, so there's nothing to do.
                // For non-persistent notifications however we need to check that the notification has been set because, for example,
                // if the app has just started the notifications need to be set again. so we do this below.
                if (!driver.hasPersistentNotifications() && !driver.notificationIsSet(alarm.id)) {
                    const notification = await Alarm_1.default.makeNotification(alarm, note);
                    this.logger().info(`Scheduling (non-persistent) notification for note ${note.id}`, notification);
                    driver.scheduleNotification(notification);
                }
                return;
            }
            if (clearAlarm) {
                this.logger().info(`Clearing notification for note ${noteId}`);
                await driver.clearNotification(alarm.id);
                await Alarm_1.default.delete(alarm.id, { sourceDescription: 'AlarmService/clearAlarm' });
            }
            if (isDeleted || !Note_1.default.needAlarm(note))
                return;
            await Alarm_1.default.save({
                note_id: note.id,
                trigger_time: note.todo_due,
            });
            // Reload alarm to get its ID
            alarm = await Alarm_1.default.byNoteId(note.id);
            const notification = await Alarm_1.default.makeNotification(alarm, note);
            this.logger().info(`Scheduling notification for note ${note.id}`, notification);
            await driver.scheduleNotification(notification);
        }
        catch (error) {
            this.logger().error('Could not update notification', error);
        }
    }
    static async updateAllNotifications() {
        this.logger().info('Updating all notifications...');
        await this.garbageCollect();
        const dueNotes = await Note_1.default.dueNotes();
        for (let i = 0; i < dueNotes.length; i++) {
            await this.updateNoteNotification(dueNotes[i]);
        }
    }
}
exports.default = AlarmService;
//# sourceMappingURL=AlarmService.js.map