"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 IWifiEvent_1 = require("./IWifiEvent");
const Validate_1 = __importDefault(require("../../Validate/Validate"));
const IWifi_1 = require("./IWifi");
/**
 * The `sos.management.wifi` API groups together methods for managing Wi-Fi setup on the device.
 *
 * #### Internal state
 *
 * The `sos.management.wifi` API may be in 3 states:
 *
 * - `disabled` - Wi-Fi is disabled. This state is persistent between reboots.
 * - `client` - Wi-Fi is in the client state, i.e., it is capable of connecting to a network, similarly to a phone or laptop. This state is persistent between reboots with all of its configuration.
 * - `ap` - Wi-Fi is in access point state, i.e., it itself becomes a Wi-Fi network that others can connect to. This state persists between reboots and will be switched to the DISABLED state.
 *
 * You can use `enableClient()`/`disable()` method to enable
 * or disable the `client` state, or you can use `enableAP()`/`disableAP()` to turn on or off the `ap` state. It is **not** possible to go
 * from `client` state to `ap` state directly, the state has to be `disabled` first.
 *
 * <details>
 *     <summary>Wi-Fi Management Capabilities</summary>
 * 		| Capability | Description |
 * 		|:------------|:-------------|
 * 		| `WIFI` | If device supports Wi-Fi setup connection |
 * 		| `WIFI_SCAN` | If device supports Wi-Fi scanning |
 * 		| `WIFI_AP` | If device supports Wi-Fi Access Point setup |
 * 		| `WIFI_STRENGTH` | If device supports Wi-Fi signal strength measurement |
 * 		| `WIFI_COUNTRY` | If device supports Wi-Fi country code configuration |
 *
 * 		If you want to check if the device supports those capabilities, use [`sos.management.supports()`](https://developers.signageos.io/sdk/sos_management/#supports).
 * </details>
 */
class Wifi {
    messagePrefix;
    postMessage;
    static MESSAGE_PREFIX = 'wifi';
    eventEmitter;
    /** @internal */
    constructor(messagePrefix, postMessage) {
        this.messagePrefix = messagePrefix;
        this.postMessage = postMessage;
        this.eventEmitter = new events_1.EventEmitter();
    }
    /**
     * The `isClientEnabled()` method checks whether the Wi-Fi is in `client` state.
     *
     * @throws Error If the Wi-Fi state is in the `ap` state.
     * @returns {Boolean} if client mode is enabled.
     * @since 4.3.0
     *
     * @example
     * const isClientEnabled = await sos.management.wifi.isClientEnabled();
     * if (!isClientEnabled) {
     * 	await sos.management.wifi.enableClient();
     * }
     */
    async isClientEnabled() {
        const { isWifiEnabled } = await this.postMessage({
            type: this.getMessage('is_enabled'),
        });
        return isWifiEnabled;
    }
    /**
     * The `enabledClient()` method switches the Wi-Fi state from `disabled` to `client` state.
     *
     * @returns {Promise<void>} A promise that resolves when the Wi-Fi is enabled in client mode.
     * @throws Error If the Wi-Fi state is in the `ap` state.
     * @since 4.3.0
     */
    async enableClient() {
        await this.postMessage({
            type: this.getMessage('enable'),
        });
    }
    /**
     * The `isAPEnabled()` method checks whether the Wi-Fi is in `ap` state.
     *
     * @returns {Boolean} If AP mode is enabled.
     * @since 4.3.0
     */
    async isAPEnabled() {
        const { isWifiAPEnabled } = await this.postMessage({
            type: this.getMessage('is_ap_enabled'),
        });
        return isWifiAPEnabled;
    }
    /**
     * Sets Wi-Fi to AP state, meaning the device will become a Wi-Fi network that other devices can connect to. It will run in WPA-Personal mode. As such, it requires an SSID (network name) and a password that different devices will use to connect.
     *
     * :::note
     * - This method is only available on the Linux platform.
     * - It is not allowed to call this method when in the CLIENT state. You must first switch to the **DISABLED** state.
     * - Before calling this method, make sure the device supports Wi-Fi AP via `sos.management.supports("WIFI_AP")`
     * :::
     *
     * @example // {@link https://github.com/signageos/applet-examples/tree/master/examples/management-js-api/wifi-access-point | Example applet with Wi-Fi access point}
     *
     * @param ssid Name of the network, max. allowed length is 32 characters.
     * @param password Password of the device, must be between 8 and 32 characters.
     * @returns {Promise<void>} A promise that resolves when the Wi-Fi is enabled in AP mode.
     * @throws Error If the Wi-Fi state is in the `client` state.
     * @since 4.3.0
     */
    async enableAP(ssid, password) {
        (0, Validate_1.default)({ ssid }).required().string();
        (0, Validate_1.default)({ password }).required().string();
        await this.postMessage({
            type: this.getMessage('enable_ap'),
            ssid,
            password,
        });
    }
    /**
     * The `disable()` method switches the Wi-Fi state to `disabled` and disconnects from the connected Wi-Fi.
     *
     * All previously configured networks will be forgotten.
     *
     * @returns {Promise<void>} A promise that resolves when the Wi-Fi is disabled.
     * @throws Error If the Wi-Fi state is in the `client` or `ap` state.
     * @since 4.3.0
     *
     * @example
     * await sos.management.wifi.disable();
     */
    async disable() {
        await this.postMessage({
            type: this.getMessage('disable'),
        });
    }
    /**
     * The `getConnectedTo()` method returns the network the device is currently connected to.
     *
     * @returns An object containing the SSID, whether the network is encrypted, and the signal strength.
     * If the device is not connected to any network, it returns `null`.
     * @throws Error If the Wi-Fi state is not in the `client` state.
     * @since 4.3.0
     *
     * @example
     * // To get the network the device is currently connected to
     * const connectedTo = await sos.management.wifi.getConnectedTo();
     * console.log(`Connected to SSID: ${connectedTo?.ssid}, Strength: ${connectedTo?.strength}`);
     */
    async getConnectedTo() {
        const wifiDevice = await this.postMessage({
            type: this.getMessage('get_connected_to'),
        });
        return wifiDevice || null;
    }
    /**
     * The `connect()` method connects the device to a specified Wi-Fi network.
     *
     * :::danger
     * On Tizen, make sure that the connection credentials are correct. If the device fails to connect, it will not retry automatically.
     * Make sure that you have a backup script or a checking mechanism in place, which will allow you to recover from the situation if the connection fails.
     * :::
     *
     * :::warning
     * Connecting to an OPEN Wi-Fi network for Tizen and WebOS is different.
     * - For Tizen, make sure that the `password` is an empty string (`''`) and in the options you have selected `OPEN` as encryption type.
     * - For WebOS, you can pass `undefined` as the `password` parameter.
     * :::
     *
     * :::info
     * The security type of Wi-Fi is mandatory for Tizen.
     * :::
     *
     * @param ssid Name of the network, max. allowed length is 32 characters.
     * @param password Password of the device, must be between 8 and 32 characters.
     * @param options Additional options for the connection.
     * @param options.hidden If the network is hidden, defaults to `false`.
     * @param options.securityType The security type of the network.
     * @param options.eap Authentication details for networks that require EAP.
     * @param options.eap.method The type of EAP authentication to use.
     * @param options.eap.identity Username or identity for authentication.
     * @param options.eap.passphrase Password or passphrase for authentication.
     * @param options.eap.phase2Auth Secondary authentication method, if required by the EAP method. Not needed for TLS.
     * @param options.eap.useCACert Whether to use a CA certificate for authentication. Not needed for TLS.
     *
     * @throws Error If the Wi-Fi state is not in the `client` state.
     * @throws Error If the `ssid` is not a string or is empty.
     * @throws Error If the `password` is not a string or is empty (if required).
     * @throws Error If the `options` is not an object or does not match the expected schema.
     * @throws Error If the `securityType` is not one of the allowed values.
     * @returns {Promise<void>} A promise that resolves when the connection is established or if the connection fails.
     * @since 4.3.0
     *
     * @example
     * // To connect to an open Wi-Fi network, e.g., WebOS
     * await sos.management.wifi.connect('MyOpenNetwork');
     *
     * // To connect an open Wi-Fi network with an empty password (Tizen)
     * await sos.management.wifi.connect('MyOpenNetwork', '', { securityType: 'OPEN' });
     *
     * // If the network is hidden
     * await sos.management.wifi.connect('MyOpenNetwork', undefined, { hidden: true });
     *
     * // To connect to an encrypted Wi-Fi network with WPA2 security
     * await sos.management.wifi.connect('MyEncryptedNetwork', 'my-password', { securityType: 'WPA2' });
     *
     * // To connect to an enterprise Wi-Fi network using EAP
     * await sos.management.wifi.connect('MyEnterpriseNetwork', undefined, {
     *   securityType: '802.1X_EAP',
     *   eap: {
     *     method: 'PEAP',
     *     identity: 'my-username',
     *     passphrase: 'my-password',
     *     phase2Auth: 'MSCHAPV2',
     *     useCACert: false,
     *   },
     * });
     */
    async connect(ssid, password, options = {}) {
        (0, Validate_1.default)({ ssid }).required().string();
        if (password !== undefined) {
            (0, Validate_1.default)({ password }).string();
        }
        (0, Validate_1.default)({ options }).object(IWifi_1.VIWifiConnectOptions);
        await this.postMessage({
            type: this.getMessage('connect'),
            ssid,
            password,
            options,
        });
    }
    /**
     * The `disconnect()` method disconnects the device from the Wi-Fi network.
     * This method will not disable the Wi-Fi client; it will just disconnect from the currently connected network.
     *
     * @returns {Promise<void>} A promise that resolves when the device is disconnected from the network.
     * @throws Error If the Wi-Fi state is not in the `client` state.
     * @since 4.3.0
     *
     * @example
     * await sos.management.wifi.disconnect();
     */
    async disconnect() {
        await this.postMessage({
            type: this.getMessage('disconnect'),
        });
    }
    /**
     * The `getCountry()` method returns the 2-letter country code to which Wi-Fi regulations the device adheres. Different countries may
     * have different regulations when it comes to the Wi-Fi networks. Under normal circumstances, everything should work with the default
     * settings. However, if you experience any problems, you might want to try changing the Wi-Fi country configuration to your country.
     *
     * @throws Error If the Wi-Fi state is not in the `client` state.
     * @returns {Promise<string | null>} A promise that resolves to the 2-letter country code from the ISO 3166 standard, or `null` if not set.
     * @since 4.3.0
     *
     * @example
     * const countryCode = await sos.management.wifi.getCountry();
     * console.log(`Current Wi-Fi country code is: ${countryCode}`); // e.g. 'US', 'CZ', etc.
     */
    async getCountry() {
        const { countryCode } = await this.postMessage({
            type: this.getMessage('get_country'),
        });
        return countryCode || null;
    }
    /**
     * The `setCountry()` method sets the 2-letter country code for the Wi-Fi settings. Different countries may
     * have different regulations when it comes to the Wi-Fi networks. Under normal circumstances, everything should work with the default
     * settings. However, if you experience any problems, you might want to try changing the Wi-Fi country configuration to your country.
     *
     * :::note
     * This method is only available on the Linux platform.
     * :::
     *
     * @param countryCode 2-letter country code from the ISO 3166 standard.
     * @returns {Promise<void>} A promise that resolves when the country code is set.
     * @throws Error If the Wi-Fi state is not in the `client` state.
     * @since 4.3.0
     *
     * @example
     * // To set the country code to the United States
     * await sos.management.wifi.setCountry('US');
     */
    async setCountry(countryCode) {
        (0, Validate_1.default)({ countryCode }).required().string();
        await this.postMessage({
            type: this.getMessage('set_country'),
            countryCode,
        });
    }
    /**
     * The `scanDevices()` method initializes a new network scan and available networks.
     *
     * @returns {Promise<IScannedDevice[]>} A promise that resolves to an array of scanned devices.
     * @throws Error If the Wi-Fi state is not in the `client` state.
     * @since 4.3.0
     *
     * @example
     * const scannedDevices = await sos.management.wifi.scanDevices();
     * scannedDevices.forEach(device => {
     * 	console.log(`Found Wi-Fi network: ${device.ssid}, Encrypted: ${device.encrypted}`);
     * });
     */
    async scanDevices() {
        const { devices } = await this.postMessage({
            type: this.getMessage('scan'),
        });
        return devices;
    }
    /**
     * The `on()` method sets up a listener, which is called whenever the specified event occurs.
     *
     * @param event The event for which to set up the listener.
     * @param listener The listener function to call when the event occurs.
     * @returns {void} Resolves when the listener is set up.
     * @since 4.3.0
     *
     * @example
     * sos.management.wifi.on(WifiEvent.CLIENT_ENABLED, () => {
     *   console.log('Wi-Fi client is enabled');
     * });
     */
    on(event, listener) {
        this.eventEmitter.on(event, listener);
    }
    /**
     * The `on()` method sets up a **one-time** listener, which is called whenever the specified event occurs.
     *
     * @param event The event for which to set up the listener.
     * @param listener The listener function to call when the event occurs.
     * @returns {void} Resolves when the listener is set up.
     * @since 4.3.0
     *
     * @example
     * sos.management.wifi.once(WifiEvent.CLIENT_CONNECTED, () => {
     * 	console.log('Wi-Fi client is connected');
     * });
     */
    once(event, listener) {
        this.eventEmitter.once(event, listener);
    }
    /**
     * The `removeListener()` method removes a listener previously set up by `on()` or `once()` methods.
     *
     * @param event The event for which to remove the listener.
     * @param listener The listener function to remove.
     * @returns {void} Resolves when the listener is removed.
     * @since 4.3.0
     */
    removeListener(event, listener) {
        this.eventEmitter.removeListener(event, listener);
    }
    /**
     * The `removeAllListeners()` method removes all listeners for a specified event or all events.
     *
     * @param event The event for which to remove all listeners. If not specified, all listeners for all events will be removed.
     * @returns {void} Resolves when all listeners are removed.
     * @since 4.3.0
     */
    removeAllListeners(event) {
        if (event) {
            this.eventEmitter.removeAllListeners(event);
        }
        else {
            this.eventEmitter.removeAllListeners();
        }
    }
    /** @internal */
    handleMessageData(data) {
        switch (data.type) {
            case this.getMessage('event_' + IWifiEvent_1.WifiEvent.CLIENT_ENABLED):
            case this.getMessage('event_' + IWifiEvent_1.WifiEvent.CLIENT_CONNECTED):
            case this.getMessage('event_' + IWifiEvent_1.WifiEvent.CLIENT_CONNECT_REJECTED):
            case this.getMessage('event_' + IWifiEvent_1.WifiEvent.CLIENT_DISCONNECTED):
            case this.getMessage('event_' + IWifiEvent_1.WifiEvent.AP_ENABLED):
            case this.getMessage('event_' + IWifiEvent_1.WifiEvent.DISABLED): {
                const typeStringWithoutEvent = this.getMessage('event_');
                const event = data.type.substring(typeStringWithoutEvent.length);
                this.eventEmitter.emit(event);
                break;
            }
            default:
        }
    }
    getMessage(name) {
        return this.messagePrefix + '.' + Wifi.MESSAGE_PREFIX + '.' + name;
    }
}
exports.default = Wifi;
//# sourceMappingURL=Wifi.js.map