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/variable';
import '@iotize/tap/service/impl/target';
import '@iotize/tap/service/impl/interface';
import { createTapBundleFromConfig, TLV_BUNDLE_CONVERTER, } from '../target-variable/tap-bundle/tap-bundle';
import { TypedDataManager } from './data-manager';
export function createTapBundlesFromConfig(tap, bundles) {
    const bundleDataStreams = {};
    for (const name in bundles) {
        bundleDataStreams[name] = createTapBundleFromConfig(tap, name, bundles[name]);
    }
    return bundleDataStreams;
}
export function createDataManagerFromTapConfig(tap, config) {
    const { bundles } = config;
    return new TypedDataManager(tap, createTapBundlesFromConfig(tap, bundles));
}
export function readDataManagerTapConfigFromTap(tap, config = {
    bundleIdNameMap: {},
    variableIdNameMap: {},
}) {
    return __awaiter(this, void 0, void 0, function* () {
        const { bundleIdNameMap, variableIdNameMap, observer } = config;
        (yield tap.service.target.connect()).successful();
        const readProfileResponse = yield tap.service.variable.readProfile();
        // if (!readProfileResponse.isSuccessful()) {
        //     switch (readProfileResponse.status) {
        //         case ResultCode.SERVICE_UNAVAILABLE:
        //             // If service is unavailable, it probably means that target is not connected yet
        //             (await tap.service.target.connect()).successful();
        //             readProfileResponse = await tap.service.variable.readProfile();
        //             break;
        //         default:
        //             // Throw error otherwise
        //             readProfileResponse.successful();
        //     }
        // }
        readProfileResponse.successful();
        const rawBundleData = readProfileResponse.rawBody();
        const profileData = TLV_BUNDLE_CONVERTER.decode(rawBundleData);
        const bundles = {};
        const variableCount = Object.keys(profileData).length;
        let index = 0;
        observer === null || observer === void 0 ? void 0 : observer.next({
            step: 'start-read-variable-config',
            profileData,
            progress: {
                loaded: index,
                total: variableCount,
            },
        });
        for (const variableId in profileData) {
            const variableIdInt = parseInt(variableId, 10);
            if (isNaN(variableIdInt)) {
                throw new Error(`Invalid variable integer identifier: ${variableId}`);
                continue;
            }
            observer === null || observer === void 0 ? void 0 : observer.next({
                step: 'read-variable',
                variableId: variableIdInt,
                progress: {
                    loaded: index + 1,
                    total: variableCount,
                },
            });
            const { bundleId, variableName, config: variableInfo, } = yield readTapVariableConfigFromTap(tap, variableIdInt, variableIdNameMap ? variableIdNameMap[variableIdInt] : undefined);
            let bundleName;
            if (bundleIdNameMap && bundleId in bundleIdNameMap) {
                bundleName = bundleIdNameMap[bundleId];
            }
            else {
                let readBundleName = (yield tap.service.bundle.getName(bundleId)).body();
                // Fix bug on firmware versions that returns fixed size for bundle name (at least until firmware v1.106)
                const endOfStringIndex = readBundleName.indexOf('\u0000');
                if (endOfStringIndex >= 0) {
                    readBundleName = readBundleName.substr(0, endOfStringIndex);
                }
                if (!readBundleName) {
                    bundleName = bundleId;
                }
                else {
                    bundleName = readBundleName;
                }
            }
            if (!(bundleName in bundles)) {
                bundles[bundleName] = {
                    id: bundleId,
                    variables: {},
                };
            }
            else {
                // TODO what to do when duplicated bundle name ?
            }
            bundles[bundleName].variables[variableName] = variableInfo;
            index++;
        }
        observer === null || observer === void 0 ? void 0 : observer.next({
            step: 'end-read-variable-config',
            progress: {
                loaded: variableCount,
                total: variableCount,
            },
        });
        return bundles;
    });
}
export function readTapVariableConfigFromTap(tap, variableId, variableName) {
    return __awaiter(this, void 0, void 0, function* () {
        const [typeResponse, bundleIdResponse, lengthResponse, metaResponse] = yield tap.service.interface.executeMultipleCalls([
            tap.service.variable.getTypeCall(variableId),
            tap.service.variable.getBundleIdCall(variableId),
            tap.service.variable.getNumberOfElementsCall(variableId),
            tap.service.variable.getMetaCall(variableId),
        ]);
        const bundleId = bundleIdResponse.body();
        const variableType = typeResponse.body();
        const length = lengthResponse.body();
        const dataType = variableType.data;
        if (!variableName) {
            const meta = metaResponse.body();
            variableName = meta.name || variableId.toString();
        }
        return {
            bundleId,
            variableName,
            config: {
                id: variableId,
                dataType,
                length,
            },
        };
    });
}
//# sourceMappingURL=data:application/json;base64, 