"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SchemaHelpers = exports.SchemaCustomTypes = void 0;
var parser_1 = require("@asyncapi/parser");
var SchemaCustomTypes;
(function (SchemaCustomTypes) {
    SchemaCustomTypes["ANY"] = "any";
    SchemaCustomTypes["RESTRICTED_ANY"] = "restricted any";
    SchemaCustomTypes["NEVER"] = "never";
    SchemaCustomTypes["UNKNOWN"] = "unknown";
})(SchemaCustomTypes = exports.SchemaCustomTypes || (exports.SchemaCustomTypes = {}));
var jsonSchemaTypes = [
    'string',
    'number',
    'integer',
    'boolean',
    'array',
    'object',
    'null',
];
var jsonSchemaKeywordTypes = {
    maxLength: 'string',
    minLength: 'string',
    pattern: 'string',
    contentMediaType: 'string',
    contentEncoding: 'string',
    multipleOf: 'number',
    maximum: 'number',
    exclusiveMaximum: 'number',
    minimum: 'number',
    exclusiveMinimum: 'number',
    items: 'array',
    maxItems: 'array',
    minItems: 'array',
    uniqueItems: 'array',
    contains: 'array',
    additionalItems: 'array',
    maxProperties: 'object',
    minProperties: 'object',
    required: 'object',
    properties: 'object',
    patternProperties: 'object',
    propertyNames: 'object',
    dependencies: 'object',
    additionalProperties: 'object',
};
var jsonSchemaKeywords = Object.keys(jsonSchemaKeywordTypes);
var SchemaHelpers = (function () {
    function SchemaHelpers() {
    }
    SchemaHelpers.toSchemaType = function (schema) {
        var _this = this;
        if (!schema || typeof schema.json !== 'function') {
            return SchemaCustomTypes.UNKNOWN;
        }
        if (schema.isBooleanSchema()) {
            if (schema.json() === true) {
                return SchemaCustomTypes.ANY;
            }
            else {
                return SchemaCustomTypes.NEVER;
            }
        }
        if (Object.keys(schema.json()).length === 0) {
            return SchemaCustomTypes.ANY;
        }
        var not = schema.not();
        if (not && this.inferType(not) === SchemaCustomTypes.ANY) {
            return SchemaCustomTypes.NEVER;
        }
        var type = this.inferType(schema);
        if (Array.isArray(type)) {
            return type.map(function (t) { return _this.toType(t, schema); }).join(' | ');
        }
        type = this.toType(type, schema);
        var combinedType = this.toCombinedType(schema);
        if (type && combinedType) {
            return "".concat(type, " ").concat(combinedType);
        }
        if (combinedType) {
            return combinedType;
        }
        if (type === 'object' && schema.title()) {
            type += ' [' + schema.title() + ']';
        }
        return type;
    };
    SchemaHelpers.applicatorSchemaName = function (idx, firstCase, otherCases, title) {
        var suffix = title ? " ".concat(title, ":") : ':';
        if (idx === 0) {
            return "".concat(firstCase).concat(suffix);
        }
        else {
            return "".concat(otherCases).concat(suffix);
        }
    };
    SchemaHelpers.prettifyValue = function (value, strict) {
        if (strict === void 0) { strict = true; }
        var typeOf = typeof value;
        if (typeOf === 'string') {
            return strict ? "\"".concat(value, "\"") : value;
        }
        if (typeOf === 'number' || typeOf === 'bigint' || typeOf === 'boolean') {
            return "".concat(value);
        }
        if (Array.isArray(value)) {
            return "[".concat(value.toString(), "]");
        }
        return JSON.stringify(value);
    };
    SchemaHelpers.humanizeConstraints = function (schema) {
        var constraints = [];
        var numberRange = this.humanizeNumberRangeConstraint(schema.minimum(), schema.exclusiveMinimum(), schema.maximum(), schema.exclusiveMaximum());
        if (numberRange !== undefined) {
            constraints.push(numberRange);
        }
        var multipleOfConstraint = this.humanizeMultipleOfConstraint(schema.multipleOf());
        if (multipleOfConstraint !== undefined) {
            constraints.push(multipleOfConstraint);
        }
        var stringRange = this.humanizeRangeConstraint('characters', schema.minLength(), schema.maxLength());
        if (stringRange !== undefined) {
            constraints.push(stringRange);
        }
        var hasUniqueItems = schema.uniqueItems();
        var arrayRange = this.humanizeRangeConstraint(hasUniqueItems ? 'unique items' : 'items', schema.minItems(), schema.maxItems());
        if (arrayRange !== undefined) {
            constraints.push(arrayRange);
        }
        var objectRange = this.humanizeRangeConstraint('properties', schema.minProperties(), schema.maxProperties());
        if (objectRange !== undefined) {
            constraints.push(objectRange);
        }
        return constraints;
    };
    SchemaHelpers.isExpandable = function (schema) {
        var type = this.inferType(schema);
        type = Array.isArray(type) ? type : [type];
        if (type.includes('object') || type.includes('array')) {
            return true;
        }
        if (schema.oneOf() ||
            schema.anyOf() ||
            schema.allOf() ||
            Object.keys(schema.properties() || {}).length > 0 ||
            schema.items() ||
            schema.not() ||
            schema.if() ||
            schema.then() ||
            schema.else()) {
            return true;
        }
        var customExtensions = this.getCustomExtensions(schema);
        if (customExtensions && Object.keys(customExtensions).length) {
            return true;
        }
        return false;
    };
    SchemaHelpers.serverVariablesToSchema = function (urlVariables) {
        var _a;
        if (!urlVariables || urlVariables.length === 0) {
            return undefined;
        }
        var obj = {};
        urlVariables.all().forEach(function (variable) {
            obj[variable.id()] = __assign({}, (variable.json() || {}));
            obj[variable.id()].type = 'string';
        });
        var json = (_a = {
                type: 'object',
                properties: obj,
                required: Object.keys(obj)
            },
            _a[this.extRenderAdditionalInfo] = false,
            _a);
        return new parser_1.SchemaV2(json);
    };
    SchemaHelpers.parametersToSchema = function (parameters) {
        var _a;
        var _this = this;
        if (!parameters || parameters.isEmpty()) {
            return undefined;
        }
        var obj = {};
        parameters.all().forEach(function (parameter) {
            var _a;
            var parameterSchema = parameter.schema();
            obj[parameter.id()] = __assign({}, ((_a = parameterSchema === null || parameterSchema === void 0 ? void 0 : parameterSchema.json()) !== null && _a !== void 0 ? _a : {}));
            obj[parameter.id()].description = parameter.hasDescription()
                ? parameter.description()
                : undefined;
            obj[parameter.id()][_this.extParameterLocation] = parameter.hasLocation()
                ? parameter.location()
                : undefined;
        });
        var json = (_a = {
                type: 'object',
                properties: obj,
                required: Object.keys(obj)
            },
            _a[this.extRenderAdditionalInfo] = false,
            _a);
        return new parser_1.SchemaV2(json);
    };
    SchemaHelpers.jsonToSchema = function (value) {
        var json = this.jsonFieldToSchema(value);
        return new parser_1.SchemaV2(json);
    };
    SchemaHelpers.getCustomExtensions = function (value) {
        if (!value || typeof value.extensions !== 'function') {
            return;
        }
        var extensions = value.extensions();
        var filteredExtensions = {};
        for (var _i = 0, _a = extensions.all(); _i < _a.length; _i++) {
            var ext = _a[_i];
            var extType = ext;
            if (!extType.id().startsWith('x-parser-') &&
                !extType.id().startsWith('x-schema-private-')) {
                filteredExtensions[extType.id()] = extType.value();
            }
        }
        return filteredExtensions;
    };
    SchemaHelpers.getDependentRequired = function (propertyName, schema) {
        var dependentRequired = [];
        var dependencies = schema.dependencies();
        if (!dependencies) {
            return;
        }
        for (var _i = 0, _a = Object.entries(dependencies); _i < _a.length; _i++) {
            var _b = _a[_i], prop = _b[0], array = _b[1];
            if (Array.isArray(array) && array.includes(propertyName)) {
                dependentRequired.push(prop);
            }
        }
        return dependentRequired.length ? dependentRequired : undefined;
    };
    SchemaHelpers.getDependentSchemas = function (schema) {
        var _a;
        var dependencies = schema.dependencies();
        if (!dependencies) {
            return;
        }
        var records = {};
        for (var _i = 0, _b = Object.entries(dependencies); _i < _b.length; _i++) {
            var _c = _b[_i], prop = _c[0], propSchema = _c[1];
            if (typeof propSchema === 'object' && !Array.isArray(propSchema)) {
                records[prop] = propSchema;
            }
        }
        if (!Object.keys(records).length) {
            return undefined;
        }
        var json = (_a = {
                type: 'object',
                properties: Object.entries(records).reduce(function (obj, _a) {
                    var propertyName = _a[0], propertySchema = _a[1];
                    obj[propertyName] = __assign({}, (propertySchema.json() || {}));
                    return obj;
                }, {})
            },
            _a[this.extRenderAdditionalInfo] = false,
            _a);
        return new parser_1.SchemaV2(json);
    };
    SchemaHelpers.toType = function (type, schema) {
        if (schema.isCircular()) {
            return type;
        }
        if (type === 'array') {
            var items = schema.items();
            if (Array.isArray(items)) {
                return this.toItemsType(items, schema);
            }
            if (!items) {
                return "array<".concat(SchemaCustomTypes.ANY, ">");
            }
            return "array<".concat(this.toSchemaType(items) || SchemaCustomTypes.UNKNOWN, ">");
        }
        return type;
    };
    SchemaHelpers.toItemsType = function (items, schema) {
        var _this = this;
        var types = items.map(function (item) { return _this.toSchemaType(item); }).join(', ');
        var additionalItems = schema.additionalItems();
        if (additionalItems !== undefined && additionalItems !== false) {
            var additionalType = additionalItems === true
                ? SchemaCustomTypes.ANY
                : this.toSchemaType(additionalItems);
            return "tuple<".concat(types ||
                SchemaCustomTypes.UNKNOWN, ", ...optional<").concat(additionalType, ">>");
        }
        return "tuple<".concat(types || SchemaCustomTypes.UNKNOWN, ">");
    };
    SchemaHelpers.toCombinedType = function (schema) {
        var oneOf = schema.oneOf();
        if (oneOf) {
            return 'oneOf';
        }
        if (schema.anyOf()) {
            return 'anyOf';
        }
        if (schema.allOf()) {
            return 'allOf';
        }
        return;
    };
    SchemaHelpers.inferType = function (schema) {
        var types = schema.type();
        if (types !== undefined) {
            if (Array.isArray(types)) {
                if (types.includes('integer') && types.includes('number')) {
                    types = types.filter(function (t) { return t !== 'integer'; });
                }
                return types.length === 1 ? types[0] : types;
            }
            return types;
        }
        var constValue = schema.const();
        if (constValue !== undefined) {
            return typeof constValue;
        }
        var enumValue = schema.enum();
        if (Array.isArray(enumValue) && enumValue.length) {
            var inferredType = Array.from(new Set(enumValue.map(function (e) { return typeof e; })));
            return inferredType.length === 1 ? inferredType[0] : inferredType;
        }
        var schemaKeys = Object.keys(schema.json() || {}) || [];
        var hasInferredTypes = jsonSchemaKeywords.some(function (key) {
            return schemaKeys.includes(key);
        });
        if (hasInferredTypes === true) {
            return SchemaCustomTypes.RESTRICTED_ANY;
        }
        if (this.toCombinedType(schema)) {
            return '';
        }
        return SchemaCustomTypes.ANY;
    };
    SchemaHelpers.humanizeNumberRangeConstraint = function (min, exclusiveMin, max, exclusiveMax) {
        var hasExclusiveMin = exclusiveMin !== undefined;
        var hasMin = min !== undefined || hasExclusiveMin;
        var hasExclusiveMax = exclusiveMax !== undefined;
        var hasMax = max !== undefined || hasExclusiveMax;
        var numberRange;
        if (hasMin && hasMax) {
            numberRange = hasExclusiveMin ? '( ' : '[ ';
            numberRange += hasExclusiveMin ? exclusiveMin : min;
            numberRange += ' .. ';
            numberRange += hasExclusiveMax ? exclusiveMax : max;
            numberRange += hasExclusiveMax ? ' )' : ' ]';
        }
        else if (hasMin) {
            numberRange = hasExclusiveMin ? '> ' : '>= ';
            numberRange += hasExclusiveMin ? exclusiveMin : min;
        }
        else if (hasMax) {
            numberRange = hasExclusiveMax ? '< ' : '<= ';
            numberRange += hasExclusiveMax ? exclusiveMax : max;
        }
        return numberRange;
    };
    SchemaHelpers.humanizeMultipleOfConstraint = function (multipleOf) {
        if (multipleOf === undefined) {
            return;
        }
        var strigifiedMultipleOf = multipleOf.toString(10);
        if (!/^0\.0*1$/.test(strigifiedMultipleOf)) {
            return "multiple of ".concat(strigifiedMultipleOf);
        }
        return "decimal places <= ".concat(strigifiedMultipleOf.split('.')[1].length);
    };
    SchemaHelpers.humanizeRangeConstraint = function (description, min, max) {
        var stringRange;
        if (min !== undefined && max !== undefined) {
            if (min === max) {
                stringRange = "".concat(min, " ").concat(description);
            }
            else {
                stringRange = "[ ".concat(min, " .. ").concat(max, " ] ").concat(description);
            }
        }
        else if (max !== undefined) {
            stringRange = "<= ".concat(max, " ").concat(description);
        }
        else if (min !== undefined) {
            if (min === 1) {
                stringRange = 'non-empty';
            }
            else {
                stringRange = ">= ".concat(min, " ").concat(description);
            }
        }
        return stringRange;
    };
    SchemaHelpers.jsonFieldToSchema = function (value) {
        var _a, _b, _c, _d;
        var _this = this;
        if (value === undefined || value === null) {
            return _a = {
                    type: 'string',
                    const: ''
                },
                _a[this.extRawValue] = true,
                _a;
        }
        if (typeof value !== 'object') {
            var str = typeof value.toString === 'function' ? value.toString() : value;
            return _b = {
                    type: 'string',
                    const: str
                },
                _b[this.extRawValue] = true,
                _b;
        }
        if (this.isJSONSchema(value)) {
            return value;
        }
        if (Array.isArray(value)) {
            return _c = {
                    type: 'array',
                    items: value.map(function (v) { return _this.jsonFieldToSchema(v); })
                },
                _c[this.extRenderAdditionalInfo] = false,
                _c;
        }
        return _d = {
                type: 'object',
                properties: Object.entries(value).reduce(function (obj, _a) {
                    var k = _a[0], v = _a[1];
                    obj[k] = _this.jsonFieldToSchema(v);
                    return obj;
                }, {})
            },
            _d[this.extRenderAdditionalInfo] = false,
            _d;
    };
    SchemaHelpers.isJSONSchema = function (value) {
        if (value &&
            typeof value === 'object' &&
            (jsonSchemaTypes.includes(value.type) ||
                (Array.isArray(value.type) &&
                    value.type.some(function (t) { return !jsonSchemaTypes.includes(t); })))) {
            return true;
        }
        return false;
    };
    SchemaHelpers.extRenderAdditionalInfo = 'x-schema-private-render-additional-info';
    SchemaHelpers.extRawValue = 'x-schema-private-raw-value';
    SchemaHelpers.extParameterLocation = 'x-schema-private-parameter-location';
    return SchemaHelpers;
}());
exports.SchemaHelpers = SchemaHelpers;
//# sourceMappingURL=schema.js.map