"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const events_1 = require("events");
const AppletCommandError_1 = __importDefault(require("../Error/AppletCommandError"));
const ErrorCodes_1 = __importDefault(require("../Error/ErrorCodes"));
const ErrorSuggestions_1 = __importDefault(require("../Error/ErrorSuggestions"));
const Validate_1 = __importDefault(require("../Validate/Validate"));
/**
 * In some cases, you might be interested in a complete log of what the device was doing during its operation. All of your business or technical logs can be stored in our storage for later usage. You can identify which events happened or even trigger self-repairing logic.
 *
 * All commands will be available in [Applet Command REST API](https://developers.signageos.io/api/#tag/DeviceApplet-Command) and can be downloaded historically as [CSV export](https://developers.signageos.io/api/#tag/DeviceMonitoring/paths/~1v1~1device~1%7BdeviceUid%7D~1report/get).
 */
class Command {
    messagePrefix;
    postMessage;
    static MESSAGE_PREFIX = 'command';
    eventEmitter;
    /** @internal */
    constructor(messagePrefix, postMessage) {
        this.messagePrefix = messagePrefix;
        this.postMessage = postMessage;
        this.eventEmitter = new events_1.EventEmitter();
        this.eventEmitter.setMaxListeners(40);
    }
    /**
     * The `dispatch()` method dispatches a new log record to the signageOS.
     *
     * :::warning[Dispatch throttling]
     * Sending commands from an applet is throttled, this means that after if the dispatch frequency is too high, some commands may be
     * discarded. Currently, the limit is 30 commands per 30 seconds, although this may not be fully accurate, and it's not possible to know the
     * exact limit.
     * :::
     *
     * @param command The command to be dispatched.
     * @throws {AppletCommandError} If type contains invalid characters, allowed to are `/^[a-zA-Z0-9\.\-_]+$/g`
     * @throws {AppletCommandError} If the command type is longer then 100 characters limit.
     * @throws {AppletCommandError} If the command is not an object or is missing required properties.
     * @since 1.0.3
     *
     * @example // {@link https://github.com/signageos/applet-examples/blob/master/examples/content-js-api/command/sending/ | Sending commands in Applet}
     * @example // {@link https://developers.signageos.io/api/#tag/DeviceApplet-Command/paths/~1v1~1device~1%7BdeviceUid%7D~1applet~1%7BappletUid%7D~1command/post | Rest API - Dispatching commands}
     * @example // {@link https://developers.signageos.io/api/#tag/DeviceApplet-Command/paths/~1v1~1device~1%7BdeviceUid%7D~1applet~1command/get | Rest API - Get commands}
     * @example // {@link https://developers.signageos.io/api/#tag/DeviceMonitoring/paths/~1v1~1device~1%7BdeviceUid%7D~1report/get | Rest API - Receiving historical data}
     *
     * @example
     * await sos.command.dispatch({
     *   type: 'Files.StartLoading',
     *   fileName: 'my-file',
     *   fileType: 'txt'
     * });
     */
    async dispatch(command) {
        this.checkTypeValidity(command.type);
        await this.postMessage({
            type: this.getMessage('dispatch'),
            command,
        });
    }
    /**
     * The `onCommand()` method sets up a listener, which is called whenever a new command from signageOS is received.
     *
     * @param listener The listener to be called when a new command is received.
     * @returns {void} Resolves when the listener is successfully set up.
     * @since 1.0.3
     *
     * @example // {@link https://github.com/signageos/applet-examples/blob/master/examples/content-js-api/command/receiving | Receiving commands in Applet}
     */
    onCommand(listener) {
        (0, Validate_1.default)({ listener }).required().function();
        this.eventEmitter.addListener('command', listener);
    }
    /** @internal */
    handleMessageData(data) {
        if (data.type === this.getMessage('dispatch_to_applet')) {
            const commandEvent = {
                type: 'command',
                command: data.command,
            };
            this.eventEmitter.emit('command', commandEvent);
        }
    }
    getMessage(name) {
        return this.messagePrefix + '.' + Command.MESSAGE_PREFIX + '.' + name;
    }
    checkTypeValidity(type) {
        const regex = /^[a-zA-Z0-9._-]+$/g;
        (0, Validate_1.default)({ type })
            .setError(new AppletCommandError_1.default({
            kind: 'appletCommandError',
            message: 'Type contains invalid characters.',
            code: ErrorCodes_1.default.COMMAND_TYPE_NOT_VALID,
            suggestion: ErrorSuggestions_1.default.COMMAND_TYPE_NOT_VALID,
        }))
            .required()
            .string()
            .matchRegExp(regex);
        (0, Validate_1.default)({ type })
            .setError(new AppletCommandError_1.default({
            kind: 'appletCommandError',
            message: 'Type is longer then 100 characters.',
            code: ErrorCodes_1.default.COMMAND_TYPE_IS_TOO_LONG,
        }))
            .lengthMax(100);
    }
}
exports.default = Command;
//# sourceMappingURL=Command.js.map