"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const commander_1 = require("commander");
const index_1 = require("./index");
const rxjs_1 = require("rxjs");
const fs_1 = require("fs");
const pkg = tslib_1.__importStar(require("../package.json"));
Object.assign(globalThis, { WebSocket: require('ws') });
let client;
let opts;
let deviceRefObj;
function getClient() {
    if (!client) {
        opts = commander_1.program.opts();
        deviceRefObj = (0, index_1.makeDeviceRefObj)(opts['deviceRef']);
        client = (0, index_1.createMotionMasterClient)(opts['hostname']);
    }
    return client;
}
function logStringified(status) {
    console.log(JSON.stringify(status, null, 2));
}
commander_1.program
    .name('motion-master-client')
    .description('CLI to Motion Master API')
    .version(pkg.version)
    .addOption(new commander_1.Option('-s, --hostname <value>', 'connect to a running Motion Master process (e.g., localhost, 192.168.123.456, oblac-drives-76d3c210.local)').default('localhost'))
    .addOption(new commander_1.Option('-f, --format <value>', 'print the output in a format such as CSV, JSON, and so on').choices(['csv']))
    .addOption(new commander_1.Option('-p, --pretty-print', 'print the output in a more readable form, which is useful for requests that involve progress')
    .default(false)
    .conflicts('format'))
    .addOption(new commander_1.Option('-d, --device-ref <value>', 'position, address, or serial number')
    .default(0, '0 position represents the first device in a network chain')
    .argParser((value) => {
    const n = Number(value);
    return isNaN(n) ? value : n;
}))
    .addOption(new commander_1.Option('-m, --message-id <value>', 'the message ID, which uniquely identifies the request, will be generated by the client library if not specified'))
    .addOption(new commander_1.Option('-t, --request-timeout <value>', 'after sending a request, how long will the client wait for Motion Master to send the status message back').argParser((value) => {
    const n = Number(value);
    if (!Number.isInteger(n)) {
        throw new Error(`The request timeout option must be an integer. The provided value is: ${value}`);
    }
    return n;
}));
const getSystemVersionCommand = new commander_1.Command('getSystemVersion').action(() => getClient()
    .whenReady()
    .then(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
    var _a;
    const status = yield (0, rxjs_1.lastValueFrom)(client.request.getSystemVersion((_a = opts['requestTimeout']) !== null && _a !== void 0 ? _a : 3000, opts['messageId']));
    if (opts['prettyPrint']) {
        console.log(status === null || status === void 0 ? void 0 : status.version);
    }
    else {
        logStringified(status);
    }
}))
    .finally(() => client.closeSockets()));
const getDeviceInfoCommand = new commander_1.Command('getDeviceInfo').action(() => getClient()
    .whenReady()
    .then(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
    var _b, _c;
    const status = yield (0, rxjs_1.lastValueFrom)(client.request.getDeviceInfo((_b = opts['requestTimeout']) !== null && _b !== void 0 ? _b : 5000, opts['messageId']));
    if (opts['format'] === 'csv') {
        console.log(['deviceAddress', 'type', 'position', 'alias'].join(','));
        (_c = status === null || status === void 0 ? void 0 : status.devices) === null || _c === void 0 ? void 0 : _c.forEach((device) => console.log([device.deviceAddress, device.type, device.position, device.alias].join(',')));
    }
    else {
        logStringified(status);
    }
}))
    .finally(() => client.closeSockets()));
const getDeviceParameterInfoCommand = new commander_1.Command('getDeviceParameterInfo').action(() => getClient()
    .whenReady()
    .then(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
    var _d, _e;
    const status = yield (0, rxjs_1.lastValueFrom)(client.request.getDeviceParameterInfo(Object.assign({}, deviceRefObj), (_d = opts['requestTimeout']) !== null && _d !== void 0 ? _d : 10000, opts['messageId']));
    if (opts['format'] === 'csv') {
        console.log(['index', 'subindex', 'name', 'unit', 'group', 'readAccess', 'writeAccess', 'min', 'max', 'valueType'].join(','));
        (_e = status.parameters) === null || _e === void 0 ? void 0 : _e.forEach((p) => console.log([p.index, p.subindex, p.name, p.unit, p.group, p.readAccess, p.writeAccess, p.min, p.max, p.valueType].join(',')));
    }
    else {
        logStringified(status);
    }
}))
    .finally(() => client.closeSockets()));
const getDeviceParameterValuesCommand = new commander_1.Command('getDeviceParameterValues')
    .addOption(new commander_1.Option('--load-from-cache', 'load parameter values from the Motion Master cache').default(false))
    .addOption(new commander_1.Option('--send-progress', 'send progress while retrieving the parameter values from the device').default(false))
    .addArgument(new commander_1.Argument('<parameterIds...>', 'space-separated list of parameter ids, e.g. 0x2030:01 0x2110:0C'))
    .action((ids, { loadFromCache, sendProgress }) => {
    const parameters = ids.reduce((arr, id) => {
        const [index, subindex] = (0, index_1.splitParameterId)(id.trim());
        arr.push({ index, subindex, loadFromCache });
        return arr;
    }, []);
    getClient()
        .onceReady$.pipe((0, rxjs_1.mergeMap)(() => {
        var _a;
        return client.request.getDeviceParameterValues(Object.assign(Object.assign({}, deviceRefObj), { parameters, sendProgress }), (_a = opts['requestTimeout']) !== null && _a !== void 0 ? _a : 30000, opts['messageId']);
    }))
        .subscribe({
        next: (status) => {
            var _a;
            if (opts['format'] === 'csv') {
                console.log(['index', 'subindex', 'typeValue', 'intValue', 'uintValue', 'floatValue', 'stringValue', 'rawValue'].join(','));
                (_a = status.parameterValues) === null || _a === void 0 ? void 0 : _a.forEach((p) => console.log([
                    p.index,
                    p.subindex,
                    p === null || p === void 0 ? void 0 : p.typeValue,
                    p.intValue,
                    p.uintValue,
                    p.floatValue,
                    p.stringValue,
                    p.rawValue,
                ].join(',')));
            }
            else {
                logStringified(status);
            }
        },
        complete: () => client.closeSockets(),
    });
});
const getDeviceFileCommand = new commander_1.Command('getDeviceFile')
    .addArgument(new commander_1.Argument('<name>', 'name of the file to retrieve'))
    .action((name) => {
    getClient()
        .whenReady()
        .then(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
        var _a;
        const status = yield (0, rxjs_1.lastValueFrom)(client.request.getDeviceFile(Object.assign(Object.assign({}, deviceRefObj), { name }), (_a = opts['requestTimeout']) !== null && _a !== void 0 ? _a : 5000, opts['messageId']));
        if (opts['prettyPrint']) {
            if (status.content) {
                console.log((0, index_1.decodeTextContent)(status.content));
            }
            else {
                console.log(`No content for '${name}'`);
            }
        }
        else {
            logStringified(status);
        }
    }))
        .finally(() => client.closeSockets());
});
const setDeviceFileCommand = new commander_1.Command('setDeviceFile')
    .addArgument(new commander_1.Argument('<name>', 'name of the file to write to the device'))
    .addArgument(new commander_1.Argument('<srcPath>', 'path to a file on your computer to read the content from and write to the device'))
    .addOption(new commander_1.Option('--overwrite', 'overwrite the existing file on the device with the same name').default(false))
    .action((name, srcPath, { overwrite }) => {
    const content = Buffer.from((0, fs_1.readFileSync)(srcPath, { encoding: 'utf-8' }), 'utf-8');
    getClient()
        .whenReady()
        .then(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
        var _a;
        const status = yield (0, rxjs_1.lastValueFrom)(client.request.setDeviceFile(Object.assign(Object.assign({}, deviceRefObj), { name, content, overwrite }), (_a = opts['requestTimeout']) !== null && _a !== void 0 ? _a : 5000, opts['messageId']));
        logStringified(status);
    }))
        .finally(() => client.closeSockets());
});
const startOffsetDetectionCommand = new commander_1.Command('startOffsetDetection').action(() => {
    getClient()
        .onceReady$.pipe((0, rxjs_1.mergeMap)(() => { var _a; return client.request.startOffsetDetection(Object.assign({}, deviceRefObj), (_a = opts['requestTimeout']) !== null && _a !== void 0 ? _a : 60000, opts['messageId']); }))
        .subscribe({
        next: (status) => {
            var _a, _b, _c, _d;
            if (opts['prettyPrint']) {
                const step = index_1.MotionMasterMessage.Status.OffsetDetection.Progress.Code[(_b = (_a = status.progress) === null || _a === void 0 ? void 0 : _a.code) !== null && _b !== void 0 ? _b : 0];
                console.log(`${step} (${(_d = (_c = status.progress) === null || _c === void 0 ? void 0 : _c.percentage) !== null && _d !== void 0 ? _d : 0}%)`);
            }
            else {
                logStringified(status);
            }
        },
        complete: () => client.closeSockets(),
    });
});
commander_1.program
    .addCommand(getSystemVersionCommand)
    .addCommand(getDeviceInfoCommand)
    .addCommand(getDeviceParameterInfoCommand)
    .addCommand(getDeviceParameterValuesCommand)
    .addCommand(getDeviceFileCommand)
    .addCommand(setDeviceFileCommand)
    .addCommand(startOffsetDetectionCommand);
commander_1.program.parse();
//# sourceMappingURL=cli.js.map