var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { bufferToHexString } from '@iotize/common/byte-converter';
import { promiseSerial } from '@iotize/common/promise';
import { QueueComProtocol } from '@iotize/tap/protocol/core';
import { BleConfig } from './ble-config';
import { BLEPacketBuilder } from './ble-packet-builder';
import { BLEPacketSplitter } from './ble-packet-splitter';
import { debug } from './debug';
import { InvalidBleFrameChecksum } from './errors';
/**
 * @deprecated use UniversalBleProtocolAdpater
 * Abstract class for BLE communication
 *
 * With ble communication, data is split into sub packets.
 * This class handles creation of packet chunks.
 *
 * - You must only implement the function to send one packet chunk writeLwm2mPacketChunk()
 * -
 */
export class AbstractBleProtocol extends QueueComProtocol {
    constructor(bleOptions = { mtu: BleConfig.maxPacketLengthWithoutOffset + 1 }) {
        super();
        this.bleOptions = bleOptions;
    }
    onNewLwm2mMessage(data) {
        if (this._readResolve) {
            debug('onNewLwm2mMessage()', bufferToHexString(data));
            this._readResolve(data);
        }
        else {
            console.warn(`No listener for new message... 0x${bufferToHexString(data)}`);
            this._pendingRead = data;
        }
    }
    onNewLwm2mMessageError(err) {
        console.error("Error lwm2m response...", err);
    }
    onLwm2mDataChunkError(error) {
        if (this._readReject) {
            this._readReject(error);
        }
        else {
            console.warn("No listener for read message error...", error);
        }
    }
    getLwm2mResponsePromise() {
        debug('getLwm2mResponsePromise');
        if (this._pendingRead) {
            let data = this._pendingRead;
            this._pendingRead = undefined;
            return Promise.resolve(data);
        }
        if (!this._readPromise) {
            this.createLwm2mResponsePromise();
        }
        return this._readPromise;
    }
    createLwm2mResponsePromise() {
        debug('createLwm2mResponsePromise');
        this._readPromise = new Promise((resolve, reject) => {
            this._readResolve = resolve;
            this._readReject = reject;
        });
        return this._readPromise;
    }
    // send(data: Uint8Array): Observable<Uint8Array> {
    //     debug("BLEProtocol:send() " + bufferToHexString(data));
    //     return from(
    //         this
    //             .write(data)
    //             .then(() => this.waitForLwm2mResponse())
    //             .catch((err) => {
    //                 console.error("ERROR SEND " + err);
    //                 throw err;
    //             })
    //     );
    // }
    read() {
        debug('read()...');
        if (this.packetBuilder) {
            if (this.packetBuilder.hasAllChunks()) {
                let data = this.packetBuilder.getData();
                this.packetBuilder = undefined;
                return Promise.resolve(data);
            }
            // TODO manage error
            console.warn("AbstractBleProtocol::read() There is already a read operation in progress but a new call to ::read has been made.");
        }
        return this
            .getLwm2mResponsePromise()
            .then((response) => {
            this.packetBuilder = undefined;
            return response;
        })
            .catch((err) => {
            this.packetBuilder = undefined;
            throw err;
        });
    }
    write(data) {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.packetSplitter != null) {
                console.warn('BLEProtocol', 'write', 'There are already data being sent but a new call to ::write has been made');
            }
            this.packetSplitter = BLEPacketSplitter.wrapWithChecksum(data, this.bleOptions.mtu - 1);
            let packets = this.packetSplitter.getPackets();
            let promise;
            this._pendingRead = undefined;
            this.packetBuilder = new BLEPacketBuilder(AbstractBleProtocol.RECEIVED_BUFFER_LENGTH);
            if (packets.length > 0) {
                // this.createLwm2mResponsePromise()
                //     .catch((err) => {
                //         this.onNewLwm2mMessageError(err);
                //     })
                promise = promiseSerial(packets, (packet, index) => {
                    return this.writeLwm2mPacketChunk(packet).then(value => {
                        debug(`Done sending packet ${index + 1}/${packets.length}`);
                        return value;
                    });
                });
                // packets.forEach((value: Uint8Array, index: number) => {
                //     if (!promise){
                //         promise = this.writeLwm2mPacketChunk(packets[index]);
                //     }
                //     else{
                //         promise = promise.then(() => this.writeLwm2mPacketChunk(packets[index]))
                //     }
                //     // promise.then(() => {
                //         // debug("BLEProtocol", "write", `Done sending packet ${index+1}/${packets.length}`);
                //     // });
                // });
            }
            else {
                console.warn('BLEProtocol', 'write', `Nothing to write...`);
                promise = Promise.resolve();
            }
            return promise
                .then(() => {
                this.packetSplitter = undefined;
            })
                .catch(err => {
                this.packetSplitter = undefined;
                throw err;
            });
        });
    }
    /**
     *
     * @param data data chunk
     */
    onNewLwm2mPacket(data) {
        if (!this.packetBuilder) {
            debug(`Ignoring lwm2m packet 0x${bufferToHexString(data)} as not request has been made yet`);
            return;
        }
        this.packetBuilder.append(data);
        if (this.packetBuilder.hasAllChunks()) {
            if (this.packetBuilder.isChecksumValid()) {
                this.onNewLwm2mMessage(this.packetBuilder.getData());
            }
            else {
                let error = InvalidBleFrameChecksum.create(this.packetBuilder);
                this.onLwm2mDataChunkError(error);
            }
        }
    }
}
// TODO set an option instead ?
AbstractBleProtocol.RECEIVED_BUFFER_LENGTH = 255;
//# sourceMappingURL=data:application/json;base64, 