"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var import_adapter_1 = require("./import-adapter");
var operators_1 = require("rxjs/operators");
var impl_1 = require("../../client/impl");
var logger_1 = require("../../logger");
var format_helper_1 = require("../../core/format/format-helper");
var logger = logger_1.default('TapApi');
var AbstractService = /** @class */ (function () {
    function AbstractService(client, apiConfig) {
        this.client = client;
        this.config = apiConfig;
    }
    AbstractService.prototype._call = function (options) {
        var observable = this._callObservable(options).pipe(operators_1.first());
        return observable.toPromise();
    };
    AbstractService.prototype._callObservable = function (options) {
        var args = this._convertToCommandArgs(options);
        var requestString = "CALL: " + options.methodType + " " + options.path + " body=" + (options.body instanceof Uint8Array ? format_helper_1.FormatHelper.toHexString(options.body) : JSON.stringify(options.body)) + " (" + args[0].toString() + ")";
        var response$ = this.client.command(args[0], args[1]);
        return response$.pipe(operators_1.tap(function (response) {
            logger.debug(requestString + " => " + response.toString());
        }, function (err) {
            logger.debug(requestString + " => " + err.message);
        }));
    };
    AbstractService.prototype._convertToCommandArgs = function (options) {
        return AbstractService.callToCommandArgs(options, this.config);
    };
    AbstractService.callToCommandArgs = function (options, config) {
        var path = options.path;
        // First we check if there is an alias 
        var lwm2mPath = config ? config.resolvePath(path) : options.path;
        // logger.debug(`AbstractService call: path ${options.path} resolved to lwm2m path ${lwm2mPath} (config ? ${config ? 'YES' : 'NO'})`)
        var pathConfig = config ? config.getRoute(options.methodType, path) : undefined;
        if (typeof options.bodyEncoder === "string") {
            if (!config) {
                throw new Error("Api config should be pass when using a reference to a body encoder");
            }
            options.bodyEncoder = config.getBodyConverter(options.bodyEncoder);
        }
        if (config && pathConfig && pathConfig.bodyEncoder) {
            options.bodyEncoder = config.getBodyConverter(pathConfig.bodyEncoder);
        }
        var returnTypeConverterId = options.returnTypeConverter || (pathConfig ? pathConfig.returnTypeConverter : undefined);
        var returnTypeConverter;
        if (typeof returnTypeConverterId == "string") {
            returnTypeConverter = config.getBodyConverter(returnTypeConverterId);
        }
        else {
            returnTypeConverter = returnTypeConverterId;
        }
        var lwm2mPathFilled = import_adapter_1.PathParameter.fillAllParams(lwm2mPath, options.pathParameters || {});
        var encodedPayload = AbstractService.encodeBody(options);
        var mtdTypeString = options.methodType.toUpperCase();
        if (!(mtdTypeString in impl_1.ApiRequest)) {
            throw new Error("Missing method \"" + mtdTypeString + "\"");
        }
        var command = impl_1.ApiRequest[mtdTypeString](lwm2mPathFilled, encodedPayload);
        // lazyDebug('TapApi', () => `SERVICE _call ${JSON.stringify(options)} | PATH: ${lwm2mPathFilled} | COMMAND: ${command} | RESPONSE CONVERTER: ${returnTypeConverter ? returnTypeConverter.constructor.name : 'NONE'} | BODY CONVERTER: ${options.bodyEncoder ? options.bodyEncoder.constructor.name : 'NONE'}`)
        return [command, returnTypeConverter];
    };
    /**
     * Encode body accoding to options and configuration
     */
    AbstractService.encodeBody = function (options) {
        if (typeof options.body == "undefined") {
            return new Uint8Array(0);
        }
        if (options.body instanceof Uint8Array) {
            return options.body;
        }
        var encoder = options.bodyEncoder;
        if (!encoder) {
            throw new Error("No valid converter for body type \"" + (options && options.body && options.body.constructor && options.body.constructor.name ? options.body.constructor.name : typeof options.body) + "\" (path " + options.path + ")");
        }
        if (typeof encoder === 'function') {
            return encoder(options.body);
        }
        else if (typeof encoder['encode'] === 'function') {
            return encoder['encode'](options.body);
        }
        else {
            throw new Error("Illegal argument for encoder: " + encoder + " (type " + typeof encoder + ")");
        }
    };
    return AbstractService;
}());
exports.AbstractService = AbstractService;
