"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    }
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
/// <reference path="../../../typings/main.d.ts" />
var RamlWrapper = require("../artifacts/raml10parserapi");
var RamlWrapperImpl = require("../artifacts/raml10parser");
var factory = require("../artifacts/raml10factory");
var core = require("./parserCore");
var ramlPathMatch = require("../../util/raml-path-match");
var hl = require("../highLevelAST");
var hlimpl = require("../highLevelImpl");
var linter = require("../ast.core/linter");
var stubs = require("../stubs");
var defs = require("raml-definition-system");
var tsInterfaces = defs.tsInterfaces;
var universeDef = require("../tools/universe");
var universes = require("../tools/universe");
var Opt = require("../../Opt");
var expanderLL = require("../ast.core/expanderLL");
var proxy = require("../ast.core/LowLevelASTProxy");
var search = require("../../search/search-interface");
var llImpl = require("../jsyaml/jsyaml2lowLevel");
var json = require("../jsyaml/json2lowLevel");
var path = require("path");
var universeHelpers = require("../tools/universeHelpers");
var builder = require("../ast.core/builder");
var helpersLL = require("./helpersLL");
var messageRegistry = require("../../../resources/errorMessages");
function resolveType(p) {
    return p.highLevel().localType();
}
exports.resolveType = resolveType;
//__$helperMethod__ Runtime representation of type represented by this AST node
function runtimeType(p) {
    return p.highLevel().localType();
}
exports.runtimeType = runtimeType;
function load(pth) {
    var m = new llImpl.Project(path.dirname(pth));
    var unit = m.unit(path.basename(pth));
    if (unit) {
        if (unit.isRAMLUnit()) {
            return hlimpl.fromUnit(unit).wrapperNode();
        }
    }
    return null;
}
exports.load = load;
//__$helperMethod__ Path relative to API root
function completeRelativeUri(res) {
    var uri = '';
    var parent = res;
    do {
        res = parent; //(parent instanceof RamlWrapper.ResourceImpl) ? <RamlWrapper.Resource>parent : null;
        uri = res.relativeUri().value() + uri;
        parent = res.parent();
    } while (parent.definition().key().name == universes.Universe10.Resource.name);
    return uri;
}
exports.completeRelativeUri = completeRelativeUri;
/**
 * __$helperMethod__
 * Equivalent Library which contains all its dependencies
 * __$meta__={"name":"expand"}
 */
function expandLibrarySpec(lib) {
    return expanderLL.expandLibrary(lib);
}
exports.expandLibrarySpec = expandLibrarySpec;
/**
 * __$helperMethod__
 * Equivalent API with traits and resource types expanded
 * @expLib whether to apply library expansion or not
 * __$meta__={"name":"expand"}
 */
function expandSpec(api, expLib) {
    if (expLib === void 0) { expLib = false; }
    if (expLib) {
        return expandLibraries(api);
    }
    else {
        return expandTraitsAndResourceTypes(api);
    }
}
exports.expandSpec = expandSpec;
/**
 * Equivalent API with traits and resource types expanded
  */
function expandTraitsAndResourceTypes(api) {
    var lowLevelNode = api.highLevel().lowLevel();
    if (proxy.LowLevelProxyNode.isInstance(lowLevelNode)) {
        return api;
    }
    return expanderLL.expandTraitsAndResourceTypes(api);
}
exports.expandTraitsAndResourceTypes = expandTraitsAndResourceTypes;
/**
 * Expand traits, resource types and libraries for the API
 * __$meta__={"name":"expandLibraries"}
 */
function expandLibraries(api) {
    return expanderLL.expandLibraries(api);
}
exports.expandLibraries = expandLibraries;
//__$helperMethod__ baseUri of owning Api concatenated with completeRelativeUri
function absoluteUri(res) {
    var uri = '';
    var parent = res;
    do {
        res = parent; //(parent instanceof RamlWrapper.ResourceImpl) ? <RamlWrapper.Resource>parent : null;
        uri = res.relativeUri().value() + uri;
        parent = res.parent();
    } while (parent.definition().key().name == universes.Universe10.Resource.name);
    parent = getParent(res);
    var buri = parent.baseUri();
    var base = buri ? buri.value() : "";
    base = base ? base : '';
    if (res) {
        base = base.replace(/\/+$/, "");
    }
    uri = base + uri;
    return uri;
}
exports.absoluteUri = absoluteUri;
//__$helperMethod__ validate an instance against type
function validateInstance(res, value) {
    return res.runtimeType().validate(value).map(function (x) { return x.getMessage(); });
    //throw new Error("Fix me");
}
exports.validateInstance = validateInstance;
//__$helperMethod__ validate an instance against type
function validateInstanceWithDetailedStatuses(res, value) {
    return res.runtimeType().validate(value);
}
exports.validateInstanceWithDetailedStatuses = validateInstanceWithDetailedStatuses;
/**
 * __$helperMethod__
 * Retrieve all traits including those defined in libraries
 * __$meta__{"name":"traits","override":true}
 */
function traitsPrimary(a) {
    return allTraits(a);
}
exports.traitsPrimary = traitsPrimary;
/**
 * __$helperMethod__ Retrieve all traits including those defined in libraries
 * __$meta__{"deprecated":true}
 */
function allTraits(a) {
    if (a.highLevel().lowLevel().actual().libExpanded) {
        return a.traits_original();
    }
    return helpersLL.allTraits(a.highLevel(), true).map(function (x) { return x.wrapperNode(); });
}
exports.allTraits = allTraits;
/**
 * __$helperMethod__
 * Retrieve all resource types including those defined in libraries
 * __$meta__{"name":"resourceTypes","override":true}
 */
function resourceTypesPrimary(a) {
    return allResourceTypes(a);
}
exports.resourceTypesPrimary = resourceTypesPrimary;
/**
 * __$helperMethod__ Retrieve all resource types including those defined in libraries
 * __$meta__{"deprecated":true}
 */
function allResourceTypes(a) {
    if (a.highLevel().lowLevel().actual().libExpanded) {
        return a.resourceTypes_original();
    }
    return helpersLL.allResourceTypes(a.highLevel(), true).map(function (x) { return x.wrapperNode(); });
}
exports.allResourceTypes = allResourceTypes;
function relativeUriSegments(res) {
    var result = [];
    var parent = res;
    do {
        res = parent; //(parent instanceof RamlWrapper.ResourceImpl) ? <RamlWrapper.Resource>parent : null;
        result.push(res.relativeUri().value());
        parent = res.parent();
    } while (parent.definition().key().name == universes.Universe10.Resource.name);
    return result.reverse();
}
exports.relativeUriSegments = relativeUriSegments;
//__$helperMethod__ For methods of Resources returns parent resource. For methods of ResourceTypes returns null.
function parentResource(method) {
    if (RamlWrapperImpl.ResourceImpl.isInstance(method.parent())) {
        return method.parent();
    }
    return null;
}
exports.parentResource = parentResource;
/**
 * __$helperMethod__
 * Parent resource for non top level resources
 * __$meta__={"name":"parentResource"}
 */
function parent(resource) {
    var parent = resource.parent();
    if (parent.definition().key().name == universes.Universe10.Resource.name) {
        return parent;
    }
    return null;
}
exports.parent = parent;
//__$helperMethod__ Get child resource by its relative path
function childResource(container, relPath) {
    if (container == null) {
        return null;
    }
    var resources = container.resources();
    if (!resources) {
        return null;
    }
    resources = resources.filter(function (x) { return x.relativeUri().value() == relPath; });
    if (resources.length == 0) {
        return null;
    }
    return resources[0];
}
exports.childResource = childResource;
function getResource(container, path) {
    if (!container) {
        return null;
    }
    var res = null;
    for (var i = 0; i < path.length; i++) {
        res = childResource(container, path[i]);
        if (!res) {
            return null;
        }
        container = res;
    }
    return res;
}
exports.getResource = getResource;
//__$helperMethod__ Get child method by its name
function childMethod(resource, method) {
    if (!resource) {
        return null;
    }
    return resource.methods().filter(function (x) { return x.method() == method; });
}
exports.childMethod = childMethod;
function getMethod(container, path, method) {
    var resource = getResource(container, path);
    if (!resource) {
        return null;
    }
    return childMethod(resource, method);
}
exports.getMethod = getMethod;
function isApi(obj) {
    return universeHelpers.isApiSibling(obj.definition());
}
;
//__$helperMethod__ Api owning the resource as a sibling
function ownerApi(method) {
    var obj = method;
    while (!isApi(obj)) {
        obj = obj.parent();
    }
    return obj;
}
exports.ownerApi = ownerApi;
/**
 * __$helperMethod__
 * For methods of Resources: `{parent Resource relative path} {methodName}`.
 * For methods of ResourceTypes: `{parent ResourceType name} {methodName}`.
 * For other methods throws Exception.
 */
function methodId(method) {
    var parent = method.parent();
    if (RamlWrapperImpl.ResourceImpl.isInstance(parent)) {
        return completeRelativeUri(parent) + ' ' + method.method().toLowerCase();
    }
    else if (RamlWrapperImpl.ResourceTypeImpl.isInstance(parent)) {
        return parent.name() + ' ' + method.method().toLowerCase();
    }
    throw new Error(linter.applyTemplate(messageRegistry.METHOD_OWNED_BY, { owner: method.definition().key().name }));
}
exports.methodId = methodId;
//__$helperMethod__ true for codes < 400 and false otherwise
function isOkRange(response) {
    var str = response.code().value();
    var err = linter.validateResponseString(str);
    if (err != null) {
        return false;
    }
    try {
        if (parseInt(str.charAt(0)) < 4) {
            return true;
        }
    }
    catch (e) { }
    return false;
}
exports.isOkRange = isOkRange;
//__$helperMethod__  Retrieve all resources of the Api
function allResources(api) {
    var resources = [];
    var visitor = function (res) {
        resources.push(res);
        res.resources().forEach(function (x) { return visitor(x); });
    };
    api.resources().forEach(function (x) { return visitor(x); });
    return resources;
}
exports.allResources = allResources;
function matchUri(apiRootRelativeUri, resource) {
    var allParameters = {};
    while (resource != null) {
        uriParameters(resource).forEach(function (x) { return allParameters[x.name()] = new ParamWrapper(x); });
        resource = parent(resource);
    }
    var result = ramlPathMatch.ramlPathMatch(completeRelativeUri(resource), allParameters, {})(apiRootRelativeUri);
    if (result) {
        return new Opt(Object.keys(result.params)
            .map(function (x) { return new ParamValue(x, result['params'][x]); }));
    }
    return Opt.empty();
}
exports.matchUri = matchUri;
var schemaContentChars = ['{', '<'];
// export function schema(body:RamlWrapper.TypeDeclaration, api:RamlWrapper.Api):Opt<SchemaDef>{
//
//     var schemaNode = body.schema();
//     if(!schemaNode){
//         return Opt.empty<SchemaDef>();
//     }
//     var schemaString = schemaNode;
//     var isContent:boolean = false;
//     schemaContentChars.forEach(x=>{try{ isContent = isContent||schemaString.indexOf(x)>=0}catch(e){}});
//     var schDef:SchemaDef;
//     if(isContent) {
//         schDef = new SchemaDef(schemaString);
//     }
//     else{
//         var globalSchemes = api.schemas().filter(x=>x.name()==schemaString);
//         if(globalSchemes.length>0){
//             schDef = new SchemaDef(globalSchemes[0].type(),globalSchemes[0].name());
//         }
//         else{
//             return Opt.empty<SchemaDef>();
//         }
//     }
//     return new Opt<SchemaDef>(schDef);
// }
/**
 * __$helperMethod__
 * Retrieve an ordered list of all uri parameters including those which are not described in the `uriParameters` node.
 * Consider a fragment of RAML specification:
 * ```yaml
 * /resource/{objectId}/{propertyId}:
 *   uriParameters:
 *     objectId:
 * ```
 * Here `propertyId` uri parameter is not described in the `uriParameters` node,
 * but it is among Resource.uriParameters().
 * __$meta__={"name":"uriParameters","override": true}
 */
function uriParametersPrimary(resource) {
    return uriParameters(resource);
}
exports.uriParametersPrimary = uriParametersPrimary;
/**
 * __$helperMethod__
 * Retrieve an ordered list of all uri parameters including those which are not described in the `uriParameters` node.
 * Consider a fragment of RAML specification:
 * ```yaml
 * /resource/{objectId}/{propertyId}:
 *   uriParameters:
 *     objectId:
 * ```
 * Here `propertyId` uri parameter is not described in the `uriParameters` node,
 * but it is among Resource.allUriParameters().
 * __$meta__={"name":"allUriParameters","deprecated":true}
 */
function uriParameters(resource) {
    var params = resource.uriParameters_original();
    if (!(RamlWrapperImpl.ResourceImpl.isInstance(resource))) {
        return params;
    }
    var uri = resource.relativeUri().value();
    var propName = universes.Universe10.ResourceBase.properties.uriParameters.name;
    return extractParams(params, uri, resource, propName);
}
exports.uriParameters = uriParameters;
/**
 * __$helperMethod__
 * Retrieve an ordered list of all base uri parameters regardless of whether they are described in `baseUriParameters` or not
 * Consider a fragment of RAML specification:
 * ```yaml
 * version: v1
 * baseUri: https://{organization}.example.com/{version}/{service}
 * baseUriParameters:
 *   service:
 * ```
 * Here `version` and `organization` are base uri parameters which are not described in the `baseUriParameters` node,
 * but they are among `Api.baseUriParameters()`.
 * __$meta__={"name":"baseUriParameters","override":true}
 */
function baseUriParametersPrimary(api) {
    return baseUriParameters(api);
}
exports.baseUriParametersPrimary = baseUriParametersPrimary;
/**
 * __$helperMethod__
 * Retrieve an ordered list of all base uri parameters regardless of whether they are described in `baseUriParameters` or not
 * Consider a fragment of RAML specification:
 * ```yaml
 * version: v1
 * baseUri: https://{organization}.example.com/{version}/{service}
 * baseUriParameters:
 *   service:
 * ```
 * Here `version` and `organization` are base uri parameters which are not described in the `baseUriParameters` node,
 * but they are among `Api.allBaseUriParameters()`.
 * __$meta__={"name":"allBaseUriParameters","deprecated":true}
 */
function baseUriParameters(api) {
    var uri = api.baseUri() ? api.baseUri().value() : '';
    var params = api.baseUriParameters_original();
    var propName = universes.Universe10.Api.properties.baseUriParameters.name;
    return extractParams(params, uri, api, propName);
}
exports.baseUriParameters = baseUriParameters;
/**
 * __$helperMethod__
 * Retrieve an ordered list of all absolute uri parameters. Returns a union of `Api.baseUriParameters()`
 * for `Api` owning the `Resource` and `Resource.uriParameters()`.
 */
function absoluteUriParameters(res) {
    var params = [];
    var parent = res;
    do {
        res = parent;
        params = uriParameters(res).concat(params);
        parent = getParent(res);
    } while (parent.definition().key().name == universes.Universe10.Resource.name);
    var api = parent;
    var baseUriParams = api.baseUriParameters();
    params = baseUriParameters(api).concat(params);
    return params;
}
exports.absoluteUriParameters = absoluteUriParameters;
function getParent(wNode) {
    var parent = wNode.parent();
    if (!parent) {
        return null;
    }
    var slaveHL = parent.highLevel().getSlaveCounterPart();
    if (slaveHL) {
        parent = slaveHL.wrapperNode();
    }
    return parent;
}
/**
 * _//_$helperMethod__
 * Protocols used by the API. Returns the `protocols` property value if it is specified.
 * Otherwise, returns protocol, specified in the base URI.
 * __$meta__={"name":"protocols","override":true}
 */
function protocolsPrimary(api) {
    return allProtocols(api);
}
exports.protocolsPrimary = protocolsPrimary;
/**
 * __$helperMethod__
 * Protocols used by the API. Returns the `protocols` property value if it is specified.
 * Otherwise, returns protocol, specified in the base URI.
 * __$meta__{"deprecated":true}
 */
function allProtocols(api) {
    return api.protocols().map(function (x) { return x.toUpperCase(); });
    //var attributeDefaults = (<RamlWrapper.ApiImpl>api).attributeDefaults();
    //var result = (<RamlWrapper.ApiImpl>api).protocols_original();
    //if(result.length!=0||!attributeDefaults){
    //    return result;
    //}
    //var baseUriAttr = api.baseUri();
    //if(baseUriAttr) {
    //    var baseUri = baseUriAttr.value();
    //    if (baseUri) {
    //        var ind = baseUri.indexOf('://');
    //        if (ind >= 0) {
    //            result = [baseUri.substring(0, ind)];
    //        }
    //        if(result.length==0){
    //            result = [ 'HTTP' ];
    //        }
    //    }
    //}
    //return result;
}
exports.allProtocols = allProtocols;
/**
 * _//_$helperMethod__
 * Returns security schemes, resource or method is secured with. If no security schemes are set at resource or method level,
 * returns schemes defined with `securedBy` at API level.
 * __$meta__={"name":"securedBy","override":true}
 */
function securedByPrimary(resourceOrMethod) {
    return allSecuredBy(resourceOrMethod);
}
exports.securedByPrimary = securedByPrimary;
/**
 * __$helperMethod__
 * Returns security schemes, resource or method is secured with. If no security schemes are set at resource or method level,
 * returns schemes defined with `securedBy` at API level.
 * __$meta__{"deprecated":true}
 */
function allSecuredBy(resourceOrMethod) {
    //var currentSecuredBy = (<RamlWrapper.ResourceBaseImpl|RamlWrapper.MethodImpl>resourceOrMethod).securedBy_original();
    //if (currentSecuredBy && currentSecuredBy.length > 0) {
    //    return currentSecuredBy;
    //}
    //
    ////instanceof, but have to avoid direct usage of instanceof in JS.
    //var key = resourceOrMethod.highLevel().definition().key();
    //if (key == universes.Universe10.Method) {
    //    var method = (<RamlWrapper.Method>resourceOrMethod);
    //    var resource = <RamlWrapper.ResourceImpl>method.parentResource();
    //    if (resource && resource.securedBy_original() && resource.securedBy_original().length > 0) {
    //        return resource.securedBy_original();
    //    }
    //    return method.ownerApi().securedBy();
    //}
    //if (key == universes.Universe10.Resource) {
    //    return (<RamlWrapper.Resource>resourceOrMethod).ownerApi().securedBy();
    //}
    return resourceOrMethod.securedBy(); //return currentSecuredBy;
}
exports.allSecuredBy = allSecuredBy;
/**
 * __$helperMethod__
 * __$meta__={"primary":true}
 */
function securitySchemeName(schemeReference) {
    var highLevel = schemeReference.highLevel();
    if (!highLevel)
        return "";
    var attributeValue = highLevel.value();
    if (!attributeValue)
        return "";
    return attributeValue.toString();
}
exports.securitySchemeName = securitySchemeName;
/**
 * __$helperMethod__
 * __$meta__={"primary":true}
 */
function securityScheme(schemeReference) {
    var highLevel = schemeReference.highLevel();
    if (!highLevel)
        return null;
    var declaration = search.findDeclarationByNode(highLevel, search.LocationKind.VALUE_COMPLETION);
    if (!declaration)
        return null;
    if (!declaration.getKind || declaration.getKind() != hl.NodeKind.NODE) {
        return null;
    }
    var result = declaration.wrapperNode();
    if (!(RamlWrapperImpl.AbstractSecuritySchemeImpl.isInstance(result))) {
        //I do not see how to avoid instanceof here
        return null;
    }
    return result;
}
exports.securityScheme = securityScheme;
/**
 * __$helperMethod__
 * __$meta__={"primary":true}
 */
function RAMLVersion(api) {
    return api.highLevel().definition().universe().version();
}
exports.RAMLVersion = RAMLVersion;
/**
 * __$helperMethod__
 * __$meta__={"primary":true}
 */
function structuredValue(reference) {
    var llNode = reference.value().lowLevel();
    var type = null;
    var hlNode = llNode.highLevelParseResult();
    if (hlNode) {
        var types = null;
        var isAnnotations = false;
        if (hlNode.isAttr()) {
            isAnnotations = universeHelpers.isAnnotationsProperty(hlNode.property());
            types = hlNode.parent().types();
        }
        else if (hlNode.isElement()) {
            types = hlNode.asElement().types();
        }
        if (types) {
            var refName = reference.name();
            var fromLib = refName.indexOf(".") >= 0;
            if (fromLib) {
                var reg = isAnnotations ? types.getAnnotationTypeRegistry() : types.getTypeRegistry();
                type = reg.get(refName);
            }
            else {
                type = isAnnotations ? types.getAnnotationType(refName) : types.getType(refName);
            }
        }
    }
    return new core.TypeInstanceImpl(llNode, type);
}
exports.structuredValue = structuredValue;
/**
 * __$helperMethod__
 * __$meta__={"name":"name","primary":true}
 */
function referenceName(reference) {
    var val = reference.highLevel().value();
    if (typeof val == 'string' || val == null) {
        return val;
    }
    else if (hlimpl.StructuredValue.isInstance(val)) {
        return val.valueName();
    }
    return null;
}
exports.referenceName = referenceName;
/**
 * __$helperMethod__
 * __$meta__={"name":"trait","primary":true}
 */
function referencedTrait(ref) {
    return referencedObject(ref);
}
exports.referencedTrait = referencedTrait;
/**
 * __$helperMethod__
 * __$meta__={"name":"annotation","primary":true}
 */
function referencedAnnotation(ref) {
    return referencedObject(ref);
}
exports.referencedAnnotation = referencedAnnotation;
/**
 * __$helperMethod__
 * __$meta__={"name":"resourceType","primary":true}
 */
function referencedResourceType(ref) {
    return referencedObject(ref);
}
exports.referencedResourceType = referencedResourceType;
function referencedObject(ref) {
    var attr = ref.highLevel();
    var parent = attr.parent();
    var vn = ref.name();
    var cands = search.referenceTargets(attr.property(), parent).filter(function (x) { return hlimpl.qName(x, parent) == vn; });
    if (cands.length == 0) {
        return null;
    }
    return cands[0].wrapperNode();
}
var toAnnotationWrappers = function (annotations, jsonNode, hlNode, unit) {
    var wrapperAnnotations = [];
    if (annotations) {
        var universe = defs.getUniverse("RAML10");
        var aProp = universe.type("Annotable").property("annotations");
        for (var _i = 0, _a = Object.keys(annotations); _i < _a.length; _i++) {
            var aName = _a[_i];
            var a = annotations[aName];
            var aJson = new json.AstNode(unit, a.value(), jsonNode, null, "(" + aName + ")");
            var aHlNode = new hlimpl.ASTPropImpl(aJson, hlNode, aProp.range(), aProp);
            var wAnnotation = new RamlWrapperImpl.AnnotationRefImpl(aHlNode);
            wrapperAnnotations.push(wAnnotation);
        }
    }
    return wrapperAnnotations;
};
function examplesFromNominal(runtimeDefinition, hlParent, isSingle, patchHL) {
    if (patchHL === void 0) { patchHL = true; }
    var llParent = hlParent.lowLevel();
    var property = hlParent.definition().property(isSingle ? "example" : "examples");
    var universe = defs.getUniverse("RAML10");
    var definition = universe.type(universeDef.Universe10.ExampleSpec.name);
    var expandables = runtimeDefinition.examples().filter(function (x) { return x != null && !x.isEmpty() && x.isSingle() == isSingle; });
    return expandables.map(function (x) {
        var obj = x.asJSON();
        var key = x.isSingle() ? "example" : null;
        var unit = llParent.unit();
        var jsonNode = new json.AstNode(unit, obj, llParent, null, key);
        var hlNode = patchHL ? new hlimpl.ASTNodeImpl(jsonNode, hlParent, definition, property) : hlParent;
        var annotations = x.annotations();
        var wrapperAnnotations = toAnnotationWrappers(annotations, jsonNode, hlNode, unit);
        var sa = x.scalarsAnnotations();
        var sa1 = {};
        Object.keys(sa).forEach(function (x) { return sa1[x] = toAnnotationWrappers(sa[x], jsonNode, hlNode, unit); });
        var result = new ExampleSpecImpl(hlNode, x, wrapperAnnotations, {
            description: function () { return sa1["description"] || []; },
            displayName: function () { return sa1["displayName"] || []; },
            strict: function () { return sa1["strict"] || []; }
        });
        return result;
    });
}
exports.examplesFromNominal = examplesFromNominal;
;
function getExpandableExamples(node, isSingle) {
    if (isSingle === void 0) { isSingle = false; }
    var runtimeDefinition = node.runtimeDefinition();
    if (!runtimeDefinition) {
        return [];
    }
    var isTopLevel = runtimeDefinition.getExtra(tsInterfaces.TOP_LEVEL_EXTRA);
    var nodeProperty = node.highLevel().property();
    var isInTypes = nodeProperty && (universeHelpers.isTypesProperty(nodeProperty)
        || universeHelpers.isSchemasProperty(nodeProperty));
    if (isInTypes || !isTopLevel) {
        var hlParent = node.highLevel();
        return examplesFromNominal(runtimeDefinition, hlParent, isSingle);
    }
    else {
        return [];
    }
}
;
/**
 * __$helperMethod__
 * __$meta__={"name":"example","primary":true}
 */
function getTypeExample(td) {
    var examples = getExpandableExamples(td, true);
    if (examples.length > 0) {
        return examples[0];
    }
    return null;
}
exports.getTypeExample = getTypeExample;
/**
 * __$helperMethod__
 * __$meta__={"name":"examples","primary":true}
 */
function getTypeExamples(td) {
    return getExpandableExamples(td);
}
exports.getTypeExamples = getTypeExamples;
/**
 * __$helperMethod__
 * __$meta__={"name":"fixedFacets","primary":true}
 */
function typeFixedFacets(td) {
    var rDef = td.runtimeDefinition();
    var obj = rDef.fixedFacets();
    if (td.kind() == universeDef.Universe10.UnionTypeDeclaration.name) {
        var builtInFacets = rDef.allFixedBuiltInFacets();
        for (var _i = 0, _a = Object.keys(builtInFacets); _i < _a.length; _i++) {
            var key = _a[_i];
            obj[key] = builtInFacets[key];
        }
    }
    else {
        var keys = Object.keys(obj);
        for (var _b = 0, keys_1 = keys; _b < keys_1.length; _b++) {
            var key = keys_1[_b];
            if (rDef.facet(key) == null) {
                delete obj[key];
            }
        }
    }
    if (Object.keys(obj).length == 0) {
        return null;
    }
    var node = new json.AstNode(null, obj);
    return new core.TypeInstanceImpl(node);
}
exports.typeFixedFacets = typeFixedFacets;
/**
 * __$helperMethod__ A base type which the current type extends, or more generally a type expression.
 * __$meta__={"name":"type","override":true}
 */
function typeValue(typeDeclaration) {
    return typeDeclaration.type_original();
    //     var attrs
    //         =typeDeclaration.highLevel().attributes(defs.universesInfo.Universe10.TypeDeclaration.properties.type.name);
    //
    //     var structuredAttrs = attrs.filter(x=>hlimpl.StructuredValue.isInstance(x.value()));
    //     if(structuredAttrs.length==0){
    //         return (<RamlWrapperImpl.TypeDeclarationImpl>typeDeclaration).type_original().map(x=>{
    //             if(x===null||x==="NULL"||x==="Null"){
    //                 return "string";
    //             }
    //             return x;
    //         });
    //     }
    //     var nullify=false;
    //     var values:string[] = attrs.map(x=>{
    //         var val = x.value();
    //         if(val==null){
    //             return null;
    //         }
    //         if(typeof(val)=="string"){
    //             return val;
    //         }
    //         else if(hlimpl.StructuredValue.isInstance(val)){
    //             nullify=true;
    //         }
    //         return val.toString();
    //     });
    //     if (nullify){
    //         return null;
    //     }
    //     return values;
}
exports.typeValue = typeValue;
/**
 * __$helperMethod__ A base type which the current type extends, or more generally a type expression.
 * __$meta__={"name":"schema","override":true}
 */
function schemaValue(typeDeclaration) {
    return typeDeclaration.schema_original();
    // var nullify=false;
    // var attrs
    //     =typeDeclaration.highLevel().attributes(defs.universesInfo.Universe10.TypeDeclaration.properties.schema.name);
    // if (nullify){
    //     return null;
    // }
    // var structuredAttrs = attrs.filter(x=>hlimpl.StructuredValue.isInstance(x.value()));
    // if(structuredAttrs.length==0){
    //     return (<RamlWrapperImpl.TypeDeclarationImpl>typeDeclaration).schema_original();
    // }
    // var values:string[] = attrs.map(x=>{
    //     var val = x.value();
    //     if(typeof(val)=="string"){
    //         return val;
    //     }
    //     else if(hlimpl.StructuredValue.isInstance(val)){
    //         nullify=true;
    //     }
    //     return val.toString();
    // });
    // if (nullify){
    //     return null;
    // }
    // return values;
}
exports.schemaValue = schemaValue;
/**
 * __$helperMethod__ Inlined supertype definition.
 * __$meta__={"name":"structuredType","primary":true}
 */
function typeStructuredValue(typeDeclaration) {
    var attrs = typeDeclaration.highLevel().attributes(defs.universesInfo.Universe10.TypeDeclaration.properties.type.name);
    attrs = attrs.concat(typeDeclaration.highLevel().attributes(defs.universesInfo.Universe10.TypeDeclaration.properties.schema.name));
    var values = attrs.map(function (x) { return x.value(); });
    for (var _i = 0, values_1 = values; _i < values_1.length; _i++) {
        var val = values_1[_i];
        if (hlimpl.StructuredValue.isInstance(val)) {
            var typeInstance = new core.TypeInstanceImpl(val.lowLevel());
            return typeInstance;
        }
    }
    return null;
}
exports.typeStructuredValue = typeStructuredValue;
/**
 * __$helperMethod__ Inlined component type definition.
 * __$meta__={"name":"structuredItems","primary":true}
 */
function itemsStructuredValue(typeDeclaration) {
    var attrs = typeDeclaration.highLevel().attributes(defs.universesInfo.Universe10.ArrayTypeDeclaration.properties.items.name);
    var values = attrs.map(function (x) { return x.value(); });
    for (var _i = 0, values_2 = values; _i < values_2.length; _i++) {
        var val = values_2[_i];
        if (hlimpl.StructuredValue.isInstance(val)) {
            var typeInstance = new core.TypeInstanceImpl(val.lowLevel());
            return typeInstance;
        }
    }
    return null;
}
exports.itemsStructuredValue = itemsStructuredValue;
/**
 * __$helperMethod__
 * Returns the root node of the AST, uses statement refers.
 * __$meta__={"name":"ast"}
 */
function referencedNode(usesDecl) {
    var ref = usesDecl.value();
    var unit = usesDecl.highLevel().lowLevel().unit().resolve(ref);
    var hlNode = unit.highLevel();
    var hlElement = hlNode.asElement();
    if (hlElement) {
        //we know, only libraries can be referenced from uses
        var wrapperNode = hlElement.wrapperNode();
        if (RamlWrapper.isLibrary(wrapperNode)) {
            wrapperNode.setAttributeDefaults(usesDecl.attributeDefaults());
            return wrapperNode;
        }
        else {
            return null;
        }
    }
    return null;
}
exports.referencedNode = referencedNode;
/**
 * __$helperMethod__
 * Anonymous type declaration defined by "items" keyword.
 * If no "items" is defined explicitly, this one is null.
 * __$meta__={"name":"items"}
 */
function getItems(typeDeclaration) {
    var attrs = typeDeclaration.highLevel().attributes(defs.universesInfo.Universe10.ArrayTypeDeclaration.properties.items.name);
    var structuredAttrs = attrs.filter(function (x) { return hlimpl.StructuredValue.isInstance(x.value()); });
    if (structuredAttrs.length == 0) {
        return typeDeclaration.items_original().map(function (x) {
            if (x === null || x === "NULL" || x === "Null") {
                return "string";
            }
            return x;
        });
    }
    var nullify = false;
    var values = attrs.map(function (x) {
        var val = x.value();
        if (val == null) {
            return null;
        }
        if (typeof (val) == "string") {
            return val;
        }
        else if (hlimpl.StructuredValue.isInstance(val)) {
            nullify = true;
        }
        return val.toString();
    });
    if (nullify) {
        return null;
    }
    return values;
}
exports.getItems = getItems;
function findComponentTypeDeclBySearch(arrayTypeDecl) {
    var typeHighLevel = arrayTypeDecl.highLevel();
    if (!typeHighLevel)
        return null;
    var attrType = typeHighLevel.attr(universes.Universe10.TypeDeclaration.properties.type.name);
    if (attrType == null)
        return null;
    var attrTypeLowLevel = attrType.lowLevel();
    if (attrTypeLowLevel == null)
        return null;
    var attrTypeValue = attrType.value();
    if (!attrTypeValue || typeof (attrTypeValue) != "string")
        return null;
    var offset = attrTypeLowLevel.end() - attrTypeValue.length + 1;
    var unit = attrType.lowLevel().unit();
    if (!unit)
        return null;
    var declaration = search.findDeclaration(unit, offset);
    if (!declaration)
        return null;
    if (!declaration.getKind || declaration.getKind() != hl.NodeKind.NODE) {
        return null;
    }
    if (!universeHelpers.isTypeDeclarationSibling(declaration.definition()))
        return null;
    return declaration.wrapperNode();
}
function findComponentTypeDeclByRuntimeType(arrayTypeDecl) {
    var runtimeType = arrayTypeDecl.runtimeType();
    if (!runtimeType)
        return null;
    if (!runtimeType.isArray() || !runtimeType.componentType)
        return null;
    var runtimeArrayType = runtimeType;
    var componentType = runtimeArrayType.componentType();
    if (!componentType)
        return null;
    var componentTypeHLSourceProvider = search.getNominalTypeSource(componentType);
    if (!componentTypeHLSourceProvider)
        return null;
    var componentTypeSource = componentTypeHLSourceProvider.getSource();
    if (!componentTypeSource)
        return null;
    if (!componentTypeSource.isElement())
        return null;
    if (!universeHelpers.isTypeDeclarationSibling(componentTypeSource.definition()))
        return null;
    var basicNodeSource = componentTypeSource.wrapperNode();
    return basicNodeSource;
}
/**
 * __$helperMethod__
 * Returns anonymous type defined by "items" keyword, or a component type if declaration can be found.
 * Does not resolve type expressions. Only returns component type declaration if it is actually defined
 * somewhere in AST.
 */
function findComponentTypeDeclaration(arrayTypeDecl) {
    var original = arrayTypeDecl.items_original();
    if (original && typeof (original) != "string" && (!Array.isArray(original) || original.length != 0)) {
        var highLevelNode = arrayTypeDecl.highLevel();
        var itemsPropName = universeDef.Universe10.ArrayTypeDeclaration.properties.items.name;
        var attr = highLevelNode.attr(itemsPropName);
        var td = highLevelNode.definition().universe().type(universeDef.Universe10.TypeDeclaration.name);
        var hasType = highLevelNode.definition().universe().type(universeDef.Universe10.ArrayTypeDeclaration.name);
        var tNode = new hlimpl.ASTNodeImpl(attr.lowLevel(), highLevelNode, td, hasType.property(itemsPropName));
        tNode.patchType(builder.doDescrimination(tNode));
    }
    var foundByRuntimeType = findComponentTypeDeclByRuntimeType(arrayTypeDecl);
    if (foundByRuntimeType)
        return foundByRuntimeType;
    return findComponentTypeDeclBySearch(arrayTypeDecl);
}
exports.findComponentTypeDeclaration = findComponentTypeDeclaration;
function extractParams(params, uri, owner, propName) {
    if (typeof (uri) != 'string') {
        uri = "";
    }
    var ownerHl = owner.highLevel();
    var definition = ownerHl.definition();
    var prop = definition.property(propName);
    var describedParams = {};
    params.forEach(function (x) {
        var arr = describedParams[x.name()];
        if (!arr) {
            arr = [];
            describedParams[x.name()] = arr;
        }
        arr.push(x);
    });
    var allParams = [];
    var prev = 0;
    var mentionedParams = {};
    for (var i = uri.indexOf('{'); i >= 0; i = uri.indexOf('{', prev)) {
        prev = uri.indexOf('}', ++i);
        if (prev < 0) {
            break;
        }
        var paramName = uri.substring(i, prev);
        mentionedParams[paramName] = true;
        if (describedParams[paramName]) {
            describedParams[paramName].forEach(function (x) { return allParams.push(x); });
        }
        else {
            var universe = definition.universe();
            var nc = universe.type(universeDef.Universe10.StringTypeDeclaration.name);
            var node = stubs.createStubNode(nc, null, paramName, ownerHl.lowLevel().unit());
            var uriParameter = factory.buildWrapperNode(node);
            var hlNode = uriParameter.highLevel();
            hlNode.setParent(ownerHl);
            uriParameter.meta().setCalculated();
            uriParameter.setName(paramName);
            hlNode.patchProp(prop);
            allParams.push(uriParameter);
        }
    }
    Object.keys(describedParams).filter(function (x) { return !mentionedParams[x]; })
        .forEach(function (x) { return describedParams[x].forEach(function (y) { return allParams.push(y); }); });
    return allParams;
}
/**
 * __$helperMethod__
 * __$meta__={"name":"parametrizedProperties","primary":true}
 */
function getTemplateParametrizedProperties(node) {
    if (node.kind() == universeDef.Universe10.Method.name || universeHelpers.isTypeDeclarationSibling(node.definition())) {
        var isInsideTemplate = false;
        var parent = node.highLevel().parent();
        while (parent != null) {
            var pDef = parent.definition();
            if (universeHelpers.isResourceTypeType(pDef) || universeHelpers.isTraitType(pDef)) {
                isInsideTemplate = true;
                break;
            }
            parent = parent.parent();
        }
        if (!isInsideTemplate) {
            return null;
        }
    }
    var highLevelNode = node.highLevel();
    if (highLevelNode == null) {
        return null;
    }
    var lowLevelNode = highLevelNode.lowLevel();
    if (lowLevelNode == null) {
        return null;
    }
    var children = lowLevelNode.children().filter(function (x) {
        var key = x.key();
        if (!key) {
            return false;
        }
        if (key.charAt(0) == "(" && key.charAt(key.length - 1) == ")") {
            return false;
        }
        return key.indexOf("<<") >= 0;
    });
    if (children.length == 0) {
        return null;
    }
    var result = new core.TypeInstanceImpl(children);
    return result;
}
exports.getTemplateParametrizedProperties = getTemplateParametrizedProperties;
var SchemaDef = /** @class */ (function () {
    function SchemaDef(_content, _name) {
        this._content = _content;
        this._name = _name;
    }
    SchemaDef.prototype.name = function () { return this._name; };
    SchemaDef.prototype.content = function () { return this._content; };
    return SchemaDef;
}());
exports.SchemaDef = SchemaDef;
var ParamValue = /** @class */ (function () {
    function ParamValue(key, value) {
        this.key = key;
        this.value = value;
    }
    return ParamValue;
}());
exports.ParamValue = ParamValue;
var ParamWrapper = /** @class */ (function () {
    function ParamWrapper(_param) {
        this._param = _param;
        this.description = _param.description() ? _param.description().value() : this.description;
        this.displayName = _param.displayName();
        //        this.enum = _param.enum();
        this.type = _param.type().length > 0 ? _param.type()[0] : "string";
        this.example = _param.example();
        this.required = _param.required();
        this.default = _param.default();
    }
    return ParamWrapper;
}());
var ExampleSpecImpl = /** @class */ (function (_super) {
    __extends(ExampleSpecImpl, _super);
    function ExampleSpecImpl(hlNode, expandable, _annotations, _scalarAnnotations) {
        var _this = _super.call(this, hlNode) || this;
        _this.expandable = expandable;
        _this._annotations = _annotations;
        _this._scalarAnnotations = _scalarAnnotations;
        return _this;
    }
    ExampleSpecImpl.prototype.value = function () {
        return this.expandable.asString();
    };
    ExampleSpecImpl.prototype.structuredValue = function () {
        var obj;
        if (this.expandable.isJSONString() || this.expandable.isYAML()) {
            obj = this.expandable.asJSON();
        }
        else {
            obj = this.expandable.original();
        }
        var llParent = this._node.lowLevel();
        var key = this.expandable.isSingle() ? "example" : null;
        var jsonNode = new json.AstNode(llParent.unit(), obj, llParent, null, key);
        return new core.TypeInstanceImpl(jsonNode);
    };
    ExampleSpecImpl.prototype.strict = function () {
        return this.expandable.strict();
    };
    ExampleSpecImpl.prototype.description = function () {
        var descriptionValue = this.expandable.description();
        if (descriptionValue == null && descriptionValue !== null) {
            return null;
        }
        var attr = stubs.createAttr(this._node.definition().property(universeDef.Universe10.ExampleSpec.properties.description.name), descriptionValue);
        attr.lowLevel().setUnit(this._node.lowLevel().unit());
        var result = new RamlWrapperImpl.MarkdownStringImpl(attr);
        return result;
    };
    ExampleSpecImpl.prototype.name = function () {
        return this.expandable.name();
    };
    ExampleSpecImpl.prototype.displayName = function () {
        return this.expandable.displayName();
    };
    ExampleSpecImpl.prototype.annotations = function () {
        return this._annotations;
    };
    ExampleSpecImpl.prototype.scalarsAnnotations = function () {
        return this._scalarAnnotations;
    };
    ExampleSpecImpl.prototype.uses = function () {
        return _super.prototype.elements.call(this, 'uses');
    };
    return ExampleSpecImpl;
}(core.BasicNodeImpl));
exports.ExampleSpecImpl = ExampleSpecImpl;
//# sourceMappingURL=wrapperHelper.js.map