"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Zones = void 0;
exports.getMethod = getMethod;
const server_api_1 = require("@signalk/server-api");
const debug_1 = require("./debug");
const debug = (0, debug_1.createDebug)('signalk-server:zones');
class Zones {
    streambundle;
    sendDelta;
    unsubscribesForPaths = {};
    constructor(streambundle, sendDelta) {
        this.streambundle = streambundle;
        this.sendDelta = sendDelta;
        streambundle.getSelfMetaBus().onValue((metaMessage) => {
            debug.enabled && debug(`${JSON.stringify(metaMessage)}`);
            const { path, value } = metaMessage;
            //send normal notification to clear out any previous notification
            //when zones field is reset
            if (value.zones === null) {
                this.sendNormalDelta(path);
                return;
            }
            if (value.zones) {
                this.watchForZones(path, value.zones, value);
            }
        });
    }
    sendNormalDelta(path) {
        this.sendDelta({
            updates: [
                {
                    values: [
                        {
                            path: `notifications.${path}`,
                            value: { state: 'normal', method: [] }
                        }
                    ]
                }
            ]
        });
    }
    watchForZones(path, zones, methods) {
        if (this.unsubscribesForPaths[path]) {
            this.unsubscribesForPaths[path]();
        }
        const tests = zones.map((zone) => {
            const { upper = Infinity, lower = -Infinity } = zone;
            return (value) => {
                return typeof value === 'number' && value < upper && value >= lower;
            };
        });
        this.unsubscribesForPaths[path] = this.streambundle
            .getSelfStream(path)
            .map((value) => {
            if (value === null) {
                return -1;
            }
            const zoneIndex = tests.findIndex((test) => test(value));
            return zoneIndex;
        })
            .skipDuplicates()
            .onValue((zoneIndex) => {
            if (debug.enabled) {
                debug(`Notify: ${path}, zone ${zoneIndex}`);
            }
            this.sendDelta(getNotificationDelta(path, zoneIndex, zones, methods));
        });
    }
}
exports.Zones = Zones;
function getMethod(state, methods) {
    const methodName = `${state}Method`;
    const method = methods[methodName];
    if (Array.isArray(method)) {
        return method;
    }
    // Explicitly null means no methods
    if (method === null) {
        return [];
    }
    // Undefined => default to visual
    return [server_api_1.ALARM_METHOD.visual];
}
function getNotificationDelta(path, zoneIndex, zones, methods) {
    let value = null;
    if (zoneIndex >= 0) {
        const { lower, upper, state, message } = zones[zoneIndex];
        value = {
            state: state,
            message: message || `${lower} < value < ${upper}`,
            method: getMethod(state, methods)
        };
    }
    else {
        // Default to "normal" zone
        value = {
            state: 'normal',
            message: 'Value is within normal range',
            method: getMethod('normal', methods)
        };
    }
    return {
        updates: [
            {
                values: [
                    {
                        path: `notifications.${path}`,
                        value: value
                    }
                ]
            }
        ]
    };
}
//# sourceMappingURL=zones.js.map