"use strict";
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.filterContextItemsByType = filterContextItemsByType;
exports.filterSupportedContextItems = filterSupportedContextItems;
exports.addOrValidateContextItemsIDs = addOrValidateContextItemsIDs;
const vscodeTypesShim_1 = require("../../../../../../../util/common/test/shims/vscodeTypesShim");
const uri_1 = require("../../../../../../../util/vs/base/common/uri");
const uuid_1 = require("../../../../../../../util/vs/base/common/uuid");
const src_1 = require("../../../../types/src");
const logger_1 = require("../../logger");
var ContextItemSchema;
(function (ContextItemSchema) {
    function is(item) {
        if (item.importance !== undefined) {
            if (typeof item.importance !== 'number' || !Number.isInteger(item.importance) || item.importance < 0 || item.importance > 100) {
                return false;
            }
        }
        if (item.id !== undefined) {
            if (typeof item.id !== 'string') {
                return false;
            }
        }
        if (item.origin !== undefined) {
            if (!src_1.ContextItemOrigin.is(item.origin)) {
                return false;
            }
        }
        return true;
    }
    ContextItemSchema.is = is;
})(ContextItemSchema || (ContextItemSchema = {}));
var TraitSchema;
(function (TraitSchema) {
    function is(item) {
        if (!ContextItemSchema.is(item)) {
            return false;
        }
        const candidate = item;
        return typeof candidate.name === 'string' && typeof candidate.value === 'string';
    }
    TraitSchema.is = is;
})(TraitSchema || (TraitSchema = {}));
var CodeSnippetSchema;
(function (CodeSnippetSchema) {
    function is(item) {
        if (!ContextItemSchema.is(item)) {
            return false;
        }
        const candidate = item;
        if (typeof candidate.uri !== 'string' || typeof candidate.value !== 'string') {
            return false;
        }
        if (candidate.additionalUris === undefined) {
            return true;
        }
        if (!Array.isArray(candidate.additionalUris)) {
            return false;
        }
        for (const uri of candidate.additionalUris) {
            if (typeof uri !== 'string') {
                return false;
            }
        }
        return true;
    }
    CodeSnippetSchema.is = is;
})(CodeSnippetSchema || (CodeSnippetSchema = {}));
var DiagnosticBagSchema;
(function (DiagnosticBagSchema) {
    function is(item) {
        if (!ContextItemSchema.is(item)) {
            return false;
        }
        const candidate = item;
        if (!(uri_1.URI.isUri(candidate.uri))) {
            return false;
        }
        if (!Array.isArray(candidate.values)) {
            return false;
        }
        for (const diagnostic of candidate.values) {
            if (!(diagnostic instanceof vscodeTypesShim_1.Diagnostic)) {
                return false;
            }
        }
        return true;
    }
    DiagnosticBagSchema.is = is;
})(DiagnosticBagSchema || (DiagnosticBagSchema = {}));
var SupportedContextItemSchema;
(function (SupportedContextItemSchema) {
    function is(item) {
        if (TraitSchema.is(item)) {
            return 'Trait';
        }
        else if (CodeSnippetSchema.is(item)) {
            return 'CodeSnippet';
        }
        else if (DiagnosticBagSchema.is(item)) {
            return 'DiagnosticBag';
        }
        return undefined;
    }
    SupportedContextItemSchema.is = is;
})(SupportedContextItemSchema || (SupportedContextItemSchema = {}));
function filterContextItemsByType(resolvedContextItems, type) {
    return resolvedContextItems
        .map(item => {
        const filteredData = item.data.filter(data => data.type === type);
        return filteredData.length > 0 ? { ...item, data: filteredData } : undefined;
    })
        .filter(r => r !== undefined);
}
function filterSupportedContextItems(contextItems) {
    const filteredItems = [];
    let invalidItemsCounter = 0;
    contextItems.forEach(item => {
        const type = SupportedContextItemSchema.is(item);
        if (type !== undefined) {
            filteredItems.push({
                ...item,
                type,
            });
        }
        else {
            invalidItemsCounter++;
        }
    });
    return [filteredItems, invalidItemsCounter];
}
/**
 *
 * Only allow alphanumeric characters and hyphens to remove symbols that could
 * be problematic when used as prompt components keys.
 */
function validateContextItemId(id) {
    return id.length > 0 && id.replaceAll(/[^a-zA-Z0-9-]/g, '').length === id.length;
}
/**
 * Assigns a random ID if it wasn't assigned by the context provider.
 * Invalid or duplicate IDs are replaced with valid ones and logged to avoid dropping the context
 * and worsen the user experience.
 */
function addOrValidateContextItemsIDs(accessor, contextItems) {
    const seenIds = new Set();
    const logTarget = accessor.get(logger_1.ICompletionsLogTargetService);
    const contextItemsWithId = [];
    for (const item of contextItems) {
        let id = item.id ?? (0, uuid_1.generateUuid)();
        if (!validateContextItemId(id)) {
            const newID = (0, uuid_1.generateUuid)();
            logger_1.logger.error(logTarget, `Invalid context item ID ${id}, replacing with ${newID}`);
            id = newID;
        }
        if (seenIds.has(id)) {
            const newID = (0, uuid_1.generateUuid)();
            logger_1.logger.error(logTarget, `Duplicate context item ID ${id}, replacing with ${newID}`);
            id = newID;
        }
        seenIds.add(id);
        contextItemsWithId.push({ ...item, id });
    }
    return contextItemsWithId;
}
//# sourceMappingURL=contextItemSchemas.js.map