"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var rxjs_1 = require("rxjs");
var operators_1 = require("rxjs/operators");
var util_1 = require("../../protocol/impl/mock/util");
var default_iotize_client_1 = require("./default-iotize-client");
var api_request_1 = require("./request/api-request");
var format_helper_1 = require("../../core/format/format-helper");
var response_1 = require("../../client/impl/response/response");
var response_2 = require("../api/response");
var logger_1 = require("../../logger");
var logger = logger_1.default('MockClient');
var MockClient = /** @class */ (function () {
    function MockClient(mapping, options) {
        this._isConnected = false;
        this._router = mapping || new util_1.Router();
        this.options = options || MockClient.DEFAULT_OPTIONS;
    }
    MockClient.prototype.addInterceptor = function (interceptor) {
        throw new Error("Method not implemented.");
    };
    MockClient.prototype.isEncryptionEnabled = function () {
        throw new Error("Method not implemented.");
    };
    /**
     *
     * TOPO add support for parameters ?
     * TODO use Shell Grammar instead ?
     *
     * @param map
     */
    MockClient.createFromMap = function (map) {
        var client = new MockClient();
        client.addRoutes(map);
        return client;
    };
    MockClient.fromMockProtocol = function (protocol) {
        var client = default_iotize_client_1.DefaultIoTizeClient.create();
        client.addComProtocol(protocol);
        return client;
    };
    Object.defineProperty(MockClient.prototype, "router", {
        get: function () {
            return this._router;
        },
        enumerable: true,
        configurable: true
    });
    MockClient.prototype.isConnected = function () {
        return this._isConnected;
    };
    MockClient.prototype.onConnectionStateChange = function () {
        throw new Error("Method not implemented.");
    };
    MockClient.prototype.addComProtocol = function (newProtocol, id) {
        this._protocol = newProtocol;
        return this;
    };
    MockClient.prototype.switchProtocol = function (type) {
        throw new Error("Method not implemented.");
    };
    MockClient.prototype.getCurrentProtocol = function () {
        throw new Error("Method not implemented.");
    };
    MockClient.prototype.connect = function () {
        var _this = this;
        var observable = rxjs_1.of(null).pipe(operators_1.delay(this.options.connect.delay));
        observable.subscribe(function () {
            _this._isConnected = true;
        });
        return observable;
    };
    MockClient.prototype.disconnect = function () {
        var _this = this;
        var observable = rxjs_1.of(null).pipe(operators_1.delay(this.options.disconnect.delay));
        observable.subscribe(function () {
            _this._isConnected = false;
        });
        return observable;
    };
    MockClient.prototype.command = function (request, bodyDecoder) {
        if (!this._isConnected) {
            throw new Error("Device is not connected");
        }
        var response = this.computeResponse(request);
        return rxjs_1.from([response])
            .pipe(operators_1.delay(this.options.command.delay));
    };
    MockClient.prototype.useComProtocol = function (protocol) {
        throw new Error("Method not implemented.");
    };
    MockClient.prototype.send = function (dataIn, bodyDecoder) {
        throw new Error("Method not implemented.");
    };
    /**
     * @deprecated in favor of addRoute
     * @param cmd
     * @param response
     */
    MockClient.prototype.mapCommandToResponse = function (cmd, response) {
        return this.addRoute(cmd, response);
    };
    MockClient.prototype.addRoute = function (command, response) {
        logger.debug("\t- Mapping command " + command.toString() + " to response " + response.toString());
        if (command instanceof RegExp) {
            throw new Error("Route with regular expressions are not implemented yet");
        }
        else if (typeof command === 'string') {
            command = util_1.Util.parseApiRequestString(command);
        }
        this.router.addRoute(command, this.createResponse(command, response));
        return this;
    };
    MockClient.prototype.addRoutes = function (map) {
        for (var pathString in map) {
            var info = map[pathString];
            var command = util_1.Util.parseApiRequestString(pathString);
            var response = this.createResponse(command, info);
            this.addRoute(command, response);
        }
        return this;
    };
    MockClient.prototype.hasRoute = function (command) {
        if (typeof command === 'string') {
            command = util_1.Util.parseApiRequestString(command);
        }
        return this.router.findRoute(command) != null;
    };
    MockClient.prototype.setEncryptionAlgo = function (algo) {
        this.encryptionAlgo = algo;
    };
    MockClient.prototype.getEncryptionAlgo = function () {
        return this.encryptionAlgo;
    };
    MockClient.prototype.enableEncryption = function (value) {
        this.options.encryption = value;
        return Promise.resolve();
    };
    MockClient.prototype.createResponse = function (command, info) {
        var response;
        if (typeof info === "number") {
            response = response_1.Response.create(info);
        }
        else if (typeof info === "string") {
            response = new response_1.Response(format_helper_1.FormatHelper.hexStringToBuffer(info));
        }
        else if (typeof info === "object") {
            if (info instanceof response_1.Response) {
                response = info;
            }
            else {
                response = response_1.Response.create(info.codeRet);
                response.setBody(info.body);
            }
        }
        else if (typeof info === "function") {
            if (command instanceof api_request_1.ApiRequest) {
                response = info(command);
            }
            else {
                return function (command) {
                    return info(command);
                };
            }
        }
        else {
            throw new Error("Invalid payload type from key " + command.toString());
        }
        return response;
    };
    MockClient.prototype.computeResponse = function (cmd) {
        var response = this.router.findRoute(cmd);
        if (response) {
            return response;
        }
        else {
            logger.debug("MockClient", "command " + cmd + " has not been mapped. Returning 404 not found");
            return response_1.Response.ERROR(response_2.ResultCode.IOTIZE_404_NOT_FOUND);
        }
    };
    MockClient.DEFAULT_OPTIONS = {
        connect: {
            delay: 100
        },
        disconnect: {
            delay: 100
        },
        command: {
            delay: 100
        },
        encryption: true
    };
    return MockClient;
}());
exports.MockClient = MockClient;
