"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Alarm = void 0;
const server_api_1 = require("@signalk/server-api");
const notificationManager_1 = require("./notificationManager");
class Alarm {
    external = false; // true when alarm was created from delta
    status = {
        silenced: false,
        acknowledged: false,
        canSilence: true,
        canAcknowledge: true,
        canClear: false
    };
    context = '';
    update = {
        values: [],
        $source: 'notificationsApi',
        timestamp: undefined,
        notificationId: undefined
    };
    path = '';
    value = {
        state: server_api_1.ALARM_STATE.normal,
        method: [server_api_1.ALARM_METHOD.visual, server_api_1.ALARM_METHOD.sound],
        message: '',
        status: this.status
    };
    /**
     * Alarm Object
     * @param notificationId Notification identifier
     */
    constructor(notificationId) {
        if (notificationId) {
            this.timeStamp();
            this.status.canClear = true;
            this.update.notificationId = notificationId;
            this.path = `notifications.${notificationId}`;
        }
    }
    /**
     * Extract and populate attributes from update and context
     * @param update Update object
     * @param context Context value
     */
    parseDelta(update, context) {
        this.context = context;
        this.update = update;
        if ((0, server_api_1.hasValues)(this.update)) {
            this.path = this.update.values[0].path;
            // ensure value is not empty
            if (this.update.values[0].value) {
                this.value = this.update.values[0].value;
            }
            else {
                this.value.message = '';
                this.value.method = [];
                this.value.state = server_api_1.ALARM_STATE.normal;
            }
        }
    }
    /**
     * Align notification alarm method with state and recorded user action
     */
    alignAlarmMethod() {
        if (this.status.acknowledged) {
            if (this.value.state === 'emergency') {
                this.value.method = [server_api_1.ALARM_METHOD.visual];
            }
            else {
                this.value.method = [];
            }
        }
        else if (this.status.silenced) {
            if (this.value.state !== 'emergency') {
                this.value.method = this.value.method.filter((i) => i !== 'sound');
            }
        }
    }
    /** Update the timestamp to the current date / time */
    timeStamp() {
        this.update.timestamp = new Date().toISOString();
    }
    /**
     * Create / update alarm from incoming update and context
     * @param update Update object
     * @param context Context value
     */
    syncFromNotificationUpdate(update, context) {
        this.external = true;
        this.status.canClear = false;
        const prevState = this.value?.state;
        this.parseDelta(update, context);
        if (prevState === server_api_1.ALARM_STATE.normal &&
            this.value.state !== server_api_1.ALARM_STATE.normal) {
            this.status.acknowledged = false;
            this.status.silenced = false;
        }
        if (!this.status.acknowledged &&
            this.value &&
            'acknowledgeStatus' in this.value) {
            this.status.acknowledged =
                this.value.acknowledgeStatus === 'Yes' ? true : false;
        }
        if (!this.status.silenced &&
            this.value &&
            'temporarySilenceStatus' in this.value) {
            this.status.silenced =
                this.value.temporarySilenceStatus === 'Yes' ? true : false;
        }
        if (this.value && 'temporarySilenceSupport' in this.value) {
            this.status.canSilence =
                this.value.temporarySilenceSupport === 'Yes' ? true : false;
        }
        if (this.value && 'acknowledgeSupport' in this.value) {
            this.status.canAcknowledge =
                this.value.acknowledgeSupport === 'Yes' ? true : false;
        }
        this.alignAlarmMethod();
    }
    /**
     * Returns true if Alarm is external (generated from incoming Delta message)
     */
    get isExternal() {
        return this.external;
    }
    /**
     * Generates and returns the delta payload for use with `handleMessage()`
     * @returns Delta message payload
     */
    get delta() {
        if ((0, server_api_1.hasValues)(this.update)) {
            this.update.values = [
                {
                    path: this.path,
                    value: this.value
                        ? Object.assign(this.value, { id: this.update.notificationId }, { status: this.status })
                        : this.value
                }
            ];
        }
        const d = { updates: [this.update] };
        if (this.external) {
            d.context = this.context;
        }
        return d;
    }
    /** Return Alarm properties */
    get properties() {
        return {
            context: this.context,
            path: this.path,
            value: this.value
        };
    }
    /**
     * Return the external key (context/path/$source) of an alarm generated from incoming Delta.
     */
    get extKey() {
        return (0, notificationManager_1.buildKey)(this.context, this.path, this.update.$source);
    }
    /**
     * Sets the path associated with the alarm.
     * @param id If supplied, the identifier will be appended to the notification path.
     */
    setPath(path, id) {
        if (path) {
            path = path.startsWith('notifications.')
                ? path
                : `notifications.${path}`;
            this.path = id ? `${path}.${id}` : path;
        }
    }
    /** Silence Alarm */
    silence() {
        if (!this.status.canSilence) {
            throw new Error('Alarm cannot be silenced!');
        }
        if (this.status.silenced || this.status.acknowledged) {
            throw new Error('Alarm already silenced or acknowledged!');
        }
        if (this.value.state === 'emergency') {
            throw new Error('Cannot silence Emergency Alarm!');
        }
        this.status.silenced = true;
        this.alignAlarmMethod();
        this.timeStamp();
    }
    /** Acknowledge Alarm */
    acknowledge() {
        if (!this.status.canAcknowledge) {
            throw new Error('Alarm cannot be acknowledged!');
        }
        if (this.status.acknowledged) {
            throw new Error('Alarm already acknowledged!');
        }
        this.status.acknowledged = true;
        this.alignAlarmMethod();
        this.timeStamp();
    }
    /**
     * Clears the Alarm by setting state = normal and resetting status.
     */
    clear() {
        if (!this.status.canClear) {
            throw new Error('Alarm cannot be cleared!');
        }
        this.value.state = server_api_1.ALARM_STATE.normal;
        this.status.silenced = false;
        this.status.acknowledged = false;
        this.timeStamp();
    }
}
exports.Alarm = Alarm;
//# sourceMappingURL=alarm.js.map