"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEFAULT_SCANNER_ID = void 0;
const events_1 = require("events");
exports.DEFAULT_SCANNER_ID = 0;
/**
 * The `sos.hardware.barcodeScanner` API provides methods for working with barcode scanners.
 * It allows starting and stopping the scanner, as well as listening for scanned data and errors.
 *
 * :::note
 * This API is experimental and may change in the future.
 * :::
 *
 * <details>
 *     <summary>Device Barcode Scanner Capabilities</summary>
 * 		| Capability | Description |
 * 		|:------------|:-------------|
 * 		| `BARCODE_SCANNER` | If device supports serial communication for Barcode Scanners |
 *
 * 		If you want to check if the device supports this capability, use [`sos.display.supports()`](https://developers.signageos.io/sdk/sos/display#supports).
 * </details>
 */
class BarcodeScanner {
    messagePrefix;
    postMessage;
    static MESSAGE_PREFIX = 'barcode_scanner';
    eventEmitter;
    /** @internal */
    constructor(messagePrefix, postMessage) {
        this.messagePrefix = messagePrefix;
        this.postMessage = postMessage;
        this.eventEmitter = new events_1.EventEmitter();
    }
    /**
     * The `getVersion()` method returns the version of the barcode scanner.
     *
     * @returns {Promise<string>} Returns a promise that resolves to the version of the barcode scanner.
     * @throws {Error} If the version cannot be retrieved.
     * @since 3.0.0
     */
    async getVersion() {
        const { version } = await this.postMessage({
            type: this.getMessage('get_version'),
        });
        return version;
    }
    /**
     * The `start()` starts the barcode scanner and starts listening for scanned data.
     * @param userOptions User options to configure the scanner.
     * @param userOptions.timeout The maximum time to wait for a scan before timing out.
     * @param userOptions.cancelPrevious If set to `true`, it will cancel any previous scanner instance with the same `scannerId`.
     * @returns Returns a promise that resolves to an object with methods to stop the scanner and listen for scanned data and errors.
     * @throws {Error} If the scanner cannot be started.
     * @throws {Error} If the scanner is already running and `cancelPrevious` option is not set to `true`.
     * @throws {Error} If any other error occurs while starting the scanner.
     * @since 3.0.0
     *
     * @example
     * // Start the barcode scanner with default options
     * const scanner = await sos.hardware.barcodeScanner.start();
     * // Listen for scanned data
     * scanner.onData((data) => {
     * 	console.log(`Scanned data: ${data}`);
     * });
     * // Listen for errors
     * scanner.onError((error) => {
     * 	console.error(`Scanner error: ${error.message}`);
     * });
     */
    async start(userOptions) {
        const defaultOptions = { scannerId: exports.DEFAULT_SCANNER_ID, timeout: 10000, cancelPrevious: false };
        const { scannerId, ...options } = { ...defaultOptions, ...userOptions };
        if (options.cancelPrevious) {
            this.eventEmitter.removeAllListeners(`scanner_id_${scannerId}.data`);
            this.eventEmitter.removeAllListeners(`scanner_id_${scannerId}.error`);
        }
        await this.postMessage({
            type: this.getMessage('start'),
            scannerId,
            options,
        });
        const onData = (listener) => {
            this.eventEmitter.addListener(`scanner_id_${scannerId}.data`, listener);
        };
        const onError = (listener) => {
            this.eventEmitter.addListener(`scanner_id_${scannerId}.error`, listener);
        };
        const stop = async () => {
            await this.postMessage({
                type: this.getMessage('stop'),
                scannerId,
            });
            this.eventEmitter.removeAllListeners(`scanner_id_${scannerId}.data`);
            this.eventEmitter.removeAllListeners(`scanner_id_${scannerId}.error`);
        };
        return { stop, onData, onError };
    }
    /** @internal */
    handleMessageData(msg) {
        switch (msg.type) {
            case this.getMessage('data'):
                this.eventEmitter.emit(`scanner_id_${msg.scannerId}.data`, msg.data);
                break;
            case this.getMessage('error'):
                this.eventEmitter.emit(`scanner_id_${msg.scannerId}.error`, msg.data);
                break;
            default:
        }
    }
    getMessage(name) {
        return [this.messagePrefix, BarcodeScanner.MESSAGE_PREFIX, name].join('.');
    }
}
exports.default = BarcodeScanner;
//# sourceMappingURL=BarcodeScanner.js.map