"use strict";
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */
var __values = (this && this.__values) || function(o) {
    var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
    if (m) return m.call(o);
    if (o && typeof o.length === "number") return {
        next: function () {
            if (o && i >= o.length) o = void 0;
            return { value: o && o[i++], done: !o };
        }
    };
    throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PublishAcknowledgementHandle = exports.queueAcknowledgeableEvent = exports.emitAcknowledgeableEvent = exports.PublishAcknowledgementHandleWrapper = exports.isValidTopic = exports.isValidTopicFilter = exports.AwsIoTDeviceSDKMetrics = exports.SDK_NAME = exports.DEFAULT_KEEP_ALIVE = exports.normalize_payload_to_buffer = exports.normalize_payload = void 0;
/**
 * Converts payload to Buffer or string regardless of the supplied type
 * @param payload The payload to convert
 * @internal
 */
function normalize_payload(payload) {
    if (payload instanceof Buffer) {
        // pass Buffer through
        return payload;
    }
    if (typeof payload === 'string') {
        // pass string through
        return payload;
    }
    if (ArrayBuffer.isView(payload)) {
        // return Buffer with view upon the same bytes (no copy)
        var view = payload;
        return Buffer.from(view.buffer, view.byteOffset, view.byteLength);
    }
    if (payload instanceof ArrayBuffer) {
        // return Buffer with view upon the same bytes (no copy)
        return Buffer.from(payload);
    }
    if (typeof payload === 'object') {
        // Convert Object to JSON string
        return JSON.stringify(payload);
    }
    if (!payload) {
        return "";
    }
    throw new TypeError("payload parameter must be a string, object, or DataView.");
}
exports.normalize_payload = normalize_payload;
/**
 * Converts payload to Buffer only, regardless of the supplied type
 * @param payload The payload to convert
 * @internal
 */
function normalize_payload_to_buffer(payload) {
    var normalized = normalize_payload(payload);
    if (typeof normalized === 'string') {
        // pass string through
        return Buffer.from(normalized);
    }
    return normalized;
}
exports.normalize_payload_to_buffer = normalize_payload_to_buffer;
/** @internal */
exports.DEFAULT_KEEP_ALIVE = 1200;
/**
 * SDK name used for metrics and identification
 * @internal
 */
exports.SDK_NAME = "IoTDeviceSDK/JS";
/**
 * IoT Device SDK Metrics Structure
 * @internal
*/
var AwsIoTDeviceSDKMetrics = /** @class */ (function () {
    function AwsIoTDeviceSDKMetrics() {
        /**
         * Name of the library
         */
        this.libraryName = exports.SDK_NAME;
    }
    return AwsIoTDeviceSDKMetrics;
}());
exports.AwsIoTDeviceSDKMetrics = AwsIoTDeviceSDKMetrics;
function isValidTopicInternal(topic, isFilter) {
    var e_1, _a;
    if (topic.length === 0 || topic.length > 65535) {
        return false;
    }
    var sawHash = false;
    try {
        for (var _b = __values(topic.split('/')), _c = _b.next(); !_c.done; _c = _b.next()) {
            var segment = _c.value;
            if (sawHash) {
                return false;
            }
            if (segment.length === 0) {
                continue;
            }
            if (segment.includes("+")) {
                if (!isFilter) {
                    return false;
                }
                if (segment.length > 1) {
                    return false;
                }
            }
            if (segment.includes("#")) {
                if (!isFilter) {
                    return false;
                }
                if (segment.length > 1) {
                    return false;
                }
                sawHash = true;
            }
        }
    }
    catch (e_1_1) { e_1 = { error: e_1_1 }; }
    finally {
        try {
            if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
        }
        finally { if (e_1) throw e_1.error; }
    }
    return true;
}
function isValidTopicFilter(topicFilter) {
    if (typeof (topicFilter) !== 'string') {
        return false;
    }
    var topicFilterAsString = topicFilter;
    return isValidTopicInternal(topicFilterAsString, true);
}
exports.isValidTopicFilter = isValidTopicFilter;
function isValidTopic(topic) {
    if (typeof (topic) !== 'string') {
        return false;
    }
    var topicAsString = topic;
    return isValidTopicInternal(topicAsString, false);
}
exports.isValidTopic = isValidTopic;
/**
 * Wrapper class containing a one-use singleton handle that can be used to trigger sending the acknowledgement (Puback in
 * QoS 1, Pubrec in QoS 2) packet for an incoming publish.
 */
var PublishAcknowledgementHandleWrapper = /** @class */ (function () {
    function PublishAcknowledgementHandleWrapper(handle) {
        this.ackHandle = handle;
    }
    /**
     * Attempt to take the acknowledgement handle held by the wrapper.  This will only succeed for the first caller;
     * after the initial call, null will be returned.  By taking the handle, the caller assumes responsibility
     * for sending the acknowledgement packet associated with the incoming publish packet.  Failing to trigger the
     * acknowledgement will cause the broker to potentially re-send the publish.
     */
    PublishAcknowledgementHandleWrapper.prototype.acquireHandle = function () {
        var handle = this.ackHandle;
        this.ackHandle = null;
        return handle;
    };
    return PublishAcknowledgementHandleWrapper;
}());
exports.PublishAcknowledgementHandleWrapper = PublishAcknowledgementHandleWrapper;
function movePublishAcknowledgementHandleWrapper(wrapper, compositionFunctor) {
    if (wrapper) {
        var handle = wrapper.acquireHandle();
        if (compositionFunctor && handle) {
            var interiorHandle_1 = handle;
            handle = new PublishAcknowledgementHandle(function () {
                interiorHandle_1.invokeAcknowledgement();
                compositionFunctor();
            });
        }
        return new PublishAcknowledgementHandleWrapper(handle);
    }
    return undefined;
}
/** @internal */
function emitAcknowledgeableEvent(emitter, ackEvent, ackEventPayload, wrapperFieldName, ackHandleWrapper, compositionFunctor) {
    ackHandleWrapper = movePublishAcknowledgementHandleWrapper(ackHandleWrapper, compositionFunctor);
    if (ackHandleWrapper) {
        ackEventPayload[wrapperFieldName] = ackHandleWrapper;
        emitter.emitWithCallback(ackEvent, function () {
            if (ackHandleWrapper) {
                var handle = ackHandleWrapper.acquireHandle();
                if (handle) {
                    // Even if corked, all listeners have had a chance to react to the event
                    // and acquire the acknowledgement handle if they wanted to.  If no one did so, then we do it ourselves.
                    handle.invokeAcknowledgement();
                }
            }
        }, ackEventPayload);
    }
    else {
        emitter.emit(ackEvent, ackEventPayload);
    }
}
exports.emitAcknowledgeableEvent = emitAcknowledgeableEvent;
/** @internal */
function queueAcknowledgeableEvent(emitter, ackEvent, ackEventPayload, wrapperFieldName, ackHandleWrapper, compositionFunctor) {
    var wrapper = movePublishAcknowledgementHandleWrapper(ackHandleWrapper, compositionFunctor);
    queueMicrotask(function () {
        if (wrapper) {
            ackEventPayload[wrapperFieldName] = wrapper;
            emitter.emitWithCallback(ackEvent, function () {
                if (wrapper) {
                    var handle = wrapper.acquireHandle();
                    if (handle) {
                        // Even if corked, all listeners have had a chance to react to the event
                        // and acquire the acknowledgement handle if they wanted to.  If no one did so, then we do it ourselves.
                        handle.invokeAcknowledgement();
                    }
                }
            }, ackEventPayload);
        }
        else {
            emitter.emit(ackEvent, ackEventPayload);
        }
    });
}
exports.queueAcknowledgeableEvent = queueAcknowledgeableEvent;
/**
 * Object that allows the holder to trigger the acknowledgement for an associated publish packet.
 */
var PublishAcknowledgementHandle = /** @class */ (function () {
    function PublishAcknowledgementHandle(acknowledgementFunction) {
        this.acknowledgementFunction = acknowledgementFunction;
    }
    /**
     * trigger the acknowledgement for an associated Publish packet
     */
    PublishAcknowledgementHandle.prototype.invokeAcknowledgement = function () {
        var acknowledgementFunction = this.acknowledgementFunction;
        this.acknowledgementFunction = undefined;
        if (acknowledgementFunction) {
            acknowledgementFunction();
        }
    };
    return PublishAcknowledgementHandle;
}());
exports.PublishAcknowledgementHandle = PublishAcknowledgementHandle;
//# sourceMappingURL=mqtt_shared.js.map