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 '@iotize/tap/service/impl/data-log';
import { isCodeError } from '@iotize/common/error';
import { TapError } from '@iotize/tap';
import { ResultCode } from '@iotize/tap/client/api';
import { TlvBundleConverter, TLVConverter } from '@iotize/tap/client/impl';
import { interval } from 'rxjs';
import { map, share, switchMap } from 'rxjs/operators';
import { DataLoggerError } from './errors';
const TAG = 'DataLogger';
/**
 * Experimental data logger class
 *
 * @experimental
 */
export class DataLogger {
    constructor(tap, converter = new DataLogSinglePacketToDataLogPacketConverter()) {
        this.tap = tap;
        this.converter = converter;
    }
    // public static fromTap(tap: Tap, options: DataLogger.Options) {
    //     const converter = DataLogPacketConverter.createFromManager(
    //         tap.bundles,
    //         tap.variables
    //     );
    //     return new DataLogger(tap, converter, options);
    // }
    isAcquisitionRunning() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.tap.service.dataLog.isRunning()).body();
        });
    }
    startAcquisition() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                (yield this.tap.service.dataLog.run()).successful();
            }
            catch (err) {
                if (isCodeError(TapError.Code.ResponseStatusError, err)) {
                    const statusCode = err.response.status;
                    if (statusCode === ResultCode.UNAUTHORIZED) {
                        throw DataLoggerError.notAuthorizedToPerformAction(`You are not authorized to start data log acquisition. Login to perform this action`, err);
                    }
                }
                throw err;
            }
        });
    }
    stopAcquisition() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                (yield this.tap.service.dataLog.stop()).successful();
            }
            catch (err) {
                if (isCodeError(TapError.Code.ResponseStatusError, err)) {
                    const statusCode = err.response.status;
                    if (statusCode === ResultCode.UNAUTHORIZED) {
                        throw DataLoggerError.notAuthorizedToPerformAction(`You are not authorized to stop data log acquisition. Login to perform this action`, err);
                    }
                }
                throw err;
            }
        });
    }
    /**
     * Dequeue one data log packet
     */
    dequeue() {
        return __awaiter(this, void 0, void 0, function* () {
            const singlePacketResponse = yield this.tap.service.dataLog.dequeueOnePacket();
            const singlePacket = singlePacketResponse.body();
            // singlePacketResponse.successful();
            // const singlePacketFrame = singlePacketResponse.rawBody();
            try {
                return this.converter.decode(singlePacket);
            }
            catch (err) {
                throw DataLoggerError.decodePacketError(singlePacket, err);
            }
        });
    }
    /**
     * Get stored packet count in Tap
     */
    getPacketCount() {
        return __awaiter(this, void 0, void 0, function* () {
            return (yield this.tap.service.dataLog.getPacketCount()).body();
        });
    }
    /**
     * Download all packets from store
     */
    download(options) {
        return interval((options === null || options === void 0 ? void 0 : options.period) || 400).pipe(switchMap((time) => this.dequeue()), map((datalogPacket, index) => {
            try {
                return {
                    type: 'new-packet',
                    progress: {
                        total: undefined,
                        loaded: index + 1,
                    },
                    packet: datalogPacket,
                };
            }
            catch (err) {
                return {
                    type: 'error',
                    error: err,
                };
            }
        }), share());
    }
}
/**
 *
 * @experimental
 */
export class DataLogSinglePacketToDataLogPacketConverter {
    constructor(tlvConverter = new TLVConverter(), bundleConverter = new TlvBundleConverter()) {
        this.tlvConverter = tlvConverter;
        this.bundleConverter = bundleConverter;
    }
    // encode(data: SinglePacket): DataLogger.RawPacket {
    //     throw new Error('Method not implemented.');
    // }
    decode(singlePacket) {
        const data = singlePacket.payload.data;
        const tlvTree = this.tlvConverter.decode(data);
        const bundleId = tlvTree.header.id;
        // console.log(tlvTree);
        const variables = tlvTree.children
            ? this.bundleConverter.decode(tlvTree)
            : {};
        const timeOffset = Date.now() - singlePacket.sendTime * 1000;
        const logTime = new Date(singlePacket.payload.logTime * 1000 + timeOffset);
        return {
            meta: {
                packetId: singlePacket.header.packetId,
                senderId: singlePacket.header.senderId,
                bundleId,
                logTime,
            },
            data: variables,
        };
    }
}
/**
 *
 * @experimental
 */
// export class DataLogPacketConverter<T = Record<string, any>>
//     implements
//     EncoderDecoder<
//     DataLogger.PacketInfo<T>,
//     { raw: Uint8Array; singlePacket: SinglePacket }
//     > {
//     constructor(
//         public meta?: BundleConfig[],
//         public rawPacketConverter: RawPacketConverter = new RawPacketConverter()
//     ) { }
//     public static createFromMeta<T>(
//         meta: BundleConfig[],
//         rawPacketConverter: RawPacketConverter = new RawPacketConverter()
//     ): DataLogPacketConverter<T> {
//         return new DataLogPacketConverter(meta, rawPacketConverter);
//     }
//     encode(
//         type: DataLogger.PacketInfo<T>
//     ): { raw: Uint8Array; singlePacket: SinglePacket } {
//         throw new Error('Method not implemented.');
//     }
//     decode(data: {
//         raw: Uint8Array;
//         singlePacket: SinglePacket;
//     }): DataLogger.PacketInfo<T> {
//         const singlePacket = data.singlePacket;
//         const dataLogPacket = this.rawPacketConverter.decode(
//             singlePacket.payload.data
//         );
//         const timeOffset = Date.now() - singlePacket.sendTime * 1000;
//         dataLogPacket.bundle.logTime = new Date(
//             singlePacket.payload.logTime * 1000 + timeOffset
//         );
//         const packet = populateDataLogPacket<T>(dataLogPacket, this.meta || []);
//         return {
//             packet,
//             rawSinglePacket: data.raw,
//             singlePacket
//         };
//     }
// }
//# sourceMappingURL=data:application/json;base64, 