import { Schema } from "mongoose";
export function jsonSchemaToMongooseSchemaDefinition(schema, schemaExtensions) {
    const res = {};
    if (schema.type === "object") {
        if (!schema.properties) {
            throw new Error("No properties defined in the schema");
        }
        else {
            for (const key in schema.properties) {
                let keySchemaDefinition = getSchemaForDefinition(schema.properties[key], schema.required && schema.required.includes(key));
                if (schemaExtensions && schemaExtensions[key]) {
                    keySchemaDefinition = Object.assign(keySchemaDefinition, schemaExtensions[key]);
                }
                res[key] = keySchemaDefinition;
            }
        }
    }
    return res;
}
function getSchemaForDefinition(definition, isRequired) {
    if (typeof definition !== "boolean") {
        let res = {
            type: Map,
        };
        switch (definition.type) {
            case "number":
            case "integer":
                res = {
                    type: Number,
                };
                if (definition.enum) {
                    res.enum = extractEnum(definition.enum);
                }
                if (definition.minimum) {
                    res.min = definition.minimum;
                }
                if (definition.maximum) {
                    res.max = definition.maximum;
                }
                break;
            case "boolean":
                res = {
                    type: Boolean,
                };
                break;
            case "string":
                if (definition.format === "date-time") {
                    res = {
                        type: Date,
                    };
                    if (definition.minimum) {
                        res.min = new Date(definition.minimum);
                    }
                    if (definition.maximum) {
                        res.max = new Date(definition.maximum);
                    }
                }
                else if (definition.format === "binary") {
                    res = {
                        type: Buffer,
                    };
                }
                else {
                    res = {
                        type: String,
                    };
                    if (definition.enum) {
                        res.enum = extractEnum(definition.enum);
                    }
                    if (definition.maxLength) {
                        res.maxlength = definition.maxLength;
                    }
                    if (definition.minLength) {
                        res.minlength = definition.minLength;
                    }
                    if (definition.pattern) {
                        res.match = definition.pattern;
                    }
                }
                break;
            case "object":
                if (definition.properties) {
                    res = {
                        type: {
                            ...jsonSchemaToMongooseSchemaDefinition(definition),
                            _id: false,
                        },
                    };
                }
                else if (definition.patternProperties ||
                    definition.additionalProperties ||
                    !definition.properties) {
                    res = {};
                    if (definition.additionalProperties &&
                        typeof definition.additionalProperties !== "boolean") {
                        res = {
                            type: Map,
                            of: {
                                ...jsonSchemaToMongooseSchemaDefinition(definition.additionalProperties),
                            },
                        };
                    }
                    else if (definition.patternProperties) {
                        if (Object.keys(definition.patternProperties).length > 1) {
                            throw new Error("Mongoose doesn't support two different types of schema at the same document level");
                        }
                        const firstKey = definition.patternProperties[Object.keys(definition.patternProperties)[0]];
                        if (typeof firstKey === "boolean") {
                            res = {
                                type: Schema.Types.Mixed,
                            };
                        }
                        else {
                            res = {
                                type: Map,
                                of: {
                                    ...jsonSchemaToMongooseSchemaDefinition(firstKey),
                                },
                            };
                        }
                    }
                    else {
                        res = {
                            type: Schema.Types.Mixed,
                        };
                    }
                }
                break;
            case "array":
                // Still a work in progress
                res = {
                    type: Array,
                };
                if (definition.items) {
                    if (typeof definition.items !== "boolean" &&
                        !Array.isArray(definition.items)) {
                        res = {
                            type: [getSchemaForDefinition(definition.items)],
                        };
                    }
                }
        }
        if (definition.default) {
            res.default = definition.default;
        }
        if (isRequired) {
            res.required = true;
        }
        return res;
    }
    else {
        return {
            type: Map,
        };
    }
}
function extractEnum(values) {
    return values
        .map(v => {
        if (Array.isArray(v)) {
            return v.filter(v => v !== null);
        }
        else if (typeof v === "object") {
            return null;
        }
        return v;
    })
        .filter(v => v !== null);
}
//# sourceMappingURL=mongoose.js.map