(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular-ru/cdk/http/utils'), require('@angular-ru/cdk/utils'), require('@angular-ru/cdk/http/typings'), require('@angular-ru/cdk/runtime')) :
    typeof define === 'function' && define.amd ? define('@angular-ru/cdk/http/decorators', ['exports', '@angular-ru/cdk/http/utils', '@angular-ru/cdk/utils', '@angular-ru/cdk/http/typings', '@angular-ru/cdk/runtime'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global['angular-ru'] = global['angular-ru'] || {}, global['angular-ru'].cdk = global['angular-ru'].cdk || {}, global['angular-ru'].cdk.http = global['angular-ru'].cdk.http || {}, global['angular-ru'].cdk.http.decorators = {}), global['angular-ru'].cdk.http.utils, global['angular-ru'].cdk.utils, global['angular-ru'].cdk.http.typings, global['angular-ru'].cdk.runtime));
}(this, (function (exports, utils$1, utils, typings, runtime) { 'use strict';

    function validateHttpParentDecorator(name, clientClass) {
        var _a;
        var local = (_a = clientClass.prototype) === null || _a === void 0 ? void 0 : _a.local;
        if (utils.isNil(local)) {
            throw new Error(name + " should be initialized before @RestClient('controllerPath')");
        }
    }

    function BaseUrl(baseUrl) {
        if (baseUrl === void 0) { baseUrl = ''; }
        return function (clientClass) {
            var _a;
            validateHttpParentDecorator('@BaseUrl', clientClass);
            var localRef = (_a = clientClass.prototype) === null || _a === void 0 ? void 0 : _a.local;
            if (utils.isNotNil(localRef)) {
                localRef.baseUrl = utils$1.replaceDoubleSlash(baseUrl);
            }
        };
    }

    function getMethodArgsRegistry(method, metaKey) {
        var _a, _b;
        return (_b = (_a = method) === null || _a === void 0 ? void 0 : _a[metaKey]) !== null && _b !== void 0 ? _b : null;
    }

    function ensureMethodArgsRegistry(method, metaKey) {
        var _a;
        var registry = getMethodArgsRegistry(method, metaKey);
        if (utils.isNil(registry)) {
            registry = new runtime.MethodArgsRegistry();
            Object.defineProperties(method, (_a = {},
                _a[metaKey] = {
                    enumerable: true,
                    configurable: true,
                    value: registry
                },
                _a));
        }
        return registry;
    }

    var META_PATH_VARIABLE = 'META_PATH_VARIABLE';
    var META_REQUEST_BODY = 'META_REQUEST_BODY';
    var META_REQUEST_PARAM = 'META_REQUEST_PARAM';
    var KEY_REQUEST_BODY = 'KEY_REQUEST_BODY';

    function ensureQueryParams(queryParams, originalMethod, args) {
        var registry = ensureMethodArgsRegistry(originalMethod, META_REQUEST_PARAM);
        if (registry.size) {
            var newParams_1 = {};
            args.forEach(function (value, index) {
                var key = registry.getNameByIndex(index);
                if (utils.isNotNil(key)) {
                    newParams_1[key] = value;
                }
            });
            return Object.assign(Object.assign({}, newParams_1), queryParams);
        }
        return queryParams;
    }

    // eslint-disable-next-line max-lines-per-function
    function mutatePathByPathVariables(options) {
        var originalMethod = options.originalMethod, args = options.args, path = options.path, pathVariables = options.pathVariables;
        var registry = ensureMethodArgsRegistry(originalMethod, META_PATH_VARIABLE);
        var definedVariables = pathVariables !== null && pathVariables !== void 0 ? pathVariables : {};
        var variableMap = new Map();
        mutateMapByMethodArgsRegistry(variableMap, args, registry);
        mutateMapByDefinedVariables(variableMap, definedVariables);
        var interpolationPath = path.toString(); // copy without mutation
        if (variableMap.size > 0) {
            interpolationPath = utils$1.ensurePathByPathVariables(interpolationPath, variableMap);
        }
        return interpolationPath;
    }
    function mutateMapByMethodArgsRegistry(variableMap, args, registry) {
        if (registry.size > 0) {
            args.forEach(function (value, index) {
                var key = registry.getNameByIndex(index);
                if (utils.isNotNil(key)) {
                    variableMap.set(key, value);
                }
            });
        }
    }
    function mutateMapByDefinedVariables(variableMap, definedVariables) {
        if (Object.keys(definedVariables).length > 0) {
            for (var key in definedVariables) {
                if (definedVariables.hasOwnProperty(key)) {
                    var value = definedVariables[key];
                    variableMap.set(key, value);
                }
            }
        }
    }

    function validateMethod(target, descriptor) {
        var isStaticMethod = target.hasOwnProperty('prototype');
        if (isStaticMethod) {
            throw new Error("Cannot support static methods with current decorator");
        }
        if (descriptor === undefined) {
            throw new Error("Current decorator can only decorate a method implementation");
        }
    }

    // eslint-disable-next-line max-lines-per-function
    function ensureDescriptorByType(_d) {
        var path = _d.path, type = _d.type, target = _d.target, descriptor = _d.descriptor, emitOptions = _d.emitOptions;
        validateMethod(target, descriptor);
        var originalMethod = descriptor.value;
        // eslint-disable-next-line max-lines-per-function
        descriptor.value = function () {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            var _a, _b, _c;
            var newPath = path.toString();
            var httpClient = this;
            var result = originalMethod.apply(httpClient, args);
            var template = (_a = result === null || result === void 0 ? void 0 : result.restTemplateRef) !== null && _a !== void 0 ? _a : null;
            if (utils.isNotNil(template)) {
                newPath = mutatePathByPathVariables({
                    args: args,
                    path: newPath,
                    originalMethod: originalMethod,
                    pathVariables: template.options.pathVariables
                });
                var bodyRegistry = ensureMethodArgsRegistry(originalMethod, META_REQUEST_BODY);
                var indexBody = bodyRegistry.getIndexByKey(KEY_REQUEST_BODY);
                var body = utils.isNil(indexBody) ? template === null || template === void 0 ? void 0 : template.options.body : (_b = template === null || template === void 0 ? void 0 : template.options.body) !== null && _b !== void 0 ? _b : args === null || args === void 0 ? void 0 : args[indexBody];
                var params = ensureQueryParams(template === null || template === void 0 ? void 0 : template.options.queryParams, originalMethod, args);
                template = template === null || template === void 0 ? void 0 : template.setPath(newPath).setMethodType(type).setBody(body).setParams(params).setEmitOptions(emitOptions).setClient(httpClient);
            }
            else {
                throw new Error('You must return observable from your method');
            }
            return (_c = template === null || template === void 0 ? void 0 : template.asObservable) === null || _c === void 0 ? void 0 : _c.call(template);
        };
        return descriptor;
    }

    function Delete(path, emitOptions) {
        if (path === void 0) { path = '/'; }
        if (emitOptions === void 0) { emitOptions = { emitFailure: true, emitSuccess: true }; }
        return function (target, _name, descriptor) { return ensureDescriptorByType({ path: path, type: typings.RequestType.DELETE, target: target, descriptor: descriptor, emitOptions: emitOptions }); };
    }

    function Get(path, emitOptions) {
        if (path === void 0) { path = '/'; }
        if (emitOptions === void 0) { emitOptions = { emitFailure: true, emitSuccess: false }; }
        return function (target, _name, descriptor) { return ensureDescriptorByType({ path: path, type: typings.RequestType.GET, target: target, descriptor: descriptor, emitOptions: emitOptions }); };
    }

    function HostUrl(hostUrl) {
        if (hostUrl === void 0) { hostUrl = ''; }
        return function (clientClass) {
            var _a;
            validateHttpParentDecorator('@HostUrl', clientClass);
            var localRef = (_a = clientClass.prototype) === null || _a === void 0 ? void 0 : _a.local;
            if (utils.isNotNil(localRef)) {
                localRef.hostUrl = hostUrl;
            }
        };
    }

    function Patch(path, emitOptions) {
        if (path === void 0) { path = '/'; }
        if (emitOptions === void 0) { emitOptions = { emitFailure: true, emitSuccess: true }; }
        return function (target, _name, descriptor) { return ensureDescriptorByType({ path: path, type: typings.RequestType.PATCH, target: target, descriptor: descriptor, emitOptions: emitOptions }); };
    }

    // eslint-disable-next-line max-lines-per-function
    function PathVariable(name) {
        return function (target, methodName, parameterIndex) {
            var key = name.trim();
            if (!key) {
                throw new Error("@PathVariable name should be initialized");
            }
            var originalMethod = target === null || target === void 0 ? void 0 : target[methodName];
            var registry = ensureMethodArgsRegistry(originalMethod, META_PATH_VARIABLE);
            registry.putIndexByName(key, methodName, parameterIndex);
        };
    }

    function Post(path, emitOptions) {
        if (path === void 0) { path = '/'; }
        if (emitOptions === void 0) { emitOptions = { emitFailure: true, emitSuccess: true }; }
        return function (target, _name, descriptor) { return ensureDescriptorByType({ path: path, type: typings.RequestType.POST, target: target, descriptor: descriptor, emitOptions: emitOptions }); };
    }

    function Put(path, emitOptions) {
        if (path === void 0) { path = '/'; }
        if (emitOptions === void 0) { emitOptions = { emitFailure: true, emitSuccess: true }; }
        return function (target, _name, descriptor) { return ensureDescriptorByType({ path: path, type: typings.RequestType.PUT, target: target, descriptor: descriptor, emitOptions: emitOptions }); };
    }

    // eslint-disable-next-line max-lines-per-function
    function RequestBody() {
        return function (target, methodName, parameterIndex) {
            var originalMethod = target === null || target === void 0 ? void 0 : target[methodName];
            var registry = ensureMethodArgsRegistry(originalMethod, META_REQUEST_BODY);
            registry.putIndexByName(KEY_REQUEST_BODY, methodName, parameterIndex);
        };
    }

    // eslint-disable-next-line max-lines-per-function
    function RequestParam(name) {
        return function (target, methodName, parameterIndex) {
            var key = name.trim();
            if (!key) {
                throw new Error("@RequestParam name should be initialized");
            }
            var originalMethod = target === null || target === void 0 ? void 0 : target[methodName];
            var registry = ensureMethodArgsRegistry(originalMethod, META_REQUEST_PARAM);
            registry.putIndexByName(key, methodName, parameterIndex);
        };
    }

    function RestClient(restUrl) {
        if (restUrl === void 0) { restUrl = ''; }
        return function (clientClass) {
            Object.defineProperties(clientClass.prototype, {
                controllerUrl: {
                    writable: true,
                    enumerable: true,
                    configurable: true,
                    value: restUrl
                },
                local: {
                    writable: true,
                    enumerable: true,
                    configurable: true,
                    value: { restUrl: restUrl }
                }
            });
        };
    }

    /**
     * Generated bundle index. Do not edit.
     */

    exports.BaseUrl = BaseUrl;
    exports.Delete = Delete;
    exports.Get = Get;
    exports.HostUrl = HostUrl;
    exports.Patch = Patch;
    exports.PathVariable = PathVariable;
    exports.Post = Post;
    exports.Put = Put;
    exports.RequestBody = RequestBody;
    exports.RequestParam = RequestParam;
    exports.RestClient = RestClient;

    Object.defineProperty(exports, '__esModule', { value: true });

})));
//# sourceMappingURL=angular-ru-http-decorators.umd.js.map
