"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PossibleTypeExtensions = void 0;
const graphql_1 = require("graphql");
const utils_1 = require("../../utils");
function PossibleTypeExtensions(context) {
    const schema = context.getSchema();
    const definedTypes = Object.create(null);
    for (const def of context.getDocument().definitions) {
        if (graphql_1.isTypeDefinitionNode(def)) {
            definedTypes[def.name.value] = def;
        }
    }
    const checkExtension = (node) => {
        const typeName = node.name.value;
        const defNode = definedTypes[typeName];
        const existingType = schema && schema.getType(typeName);
        const serviceName = node.serviceName;
        if (!serviceName)
            return;
        if (defNode) {
            const expectedKind = utils_1.defKindToExtKind[defNode.kind];
            const baseKind = defNode.kind;
            if (expectedKind !== node.kind) {
                context.reportError(utils_1.errorWithCode('EXTENSION_OF_WRONG_KIND', utils_1.logServiceAndType(serviceName, typeName) +
                    `\`${typeName}\` was originally defined as a ${baseKind} and can only be extended by a ${expectedKind}. ${serviceName} defines ${typeName} as a ${node.kind}`));
            }
        }
        else if (existingType) {
            const expectedKind = typeToExtKind(existingType);
            const baseKind = typeToKind(existingType);
            if (expectedKind !== node.kind) {
                context.reportError(utils_1.errorWithCode('EXTENSION_OF_WRONG_KIND', utils_1.logServiceAndType(serviceName, typeName) +
                    `\`${typeName}\` was originally defined as a ${baseKind} and can only be extended by a ${expectedKind}. ${serviceName} defines ${typeName} as a ${node.kind}`));
            }
        }
        else {
            context.reportError(utils_1.errorWithCode('EXTENSION_WITH_NO_BASE', utils_1.logServiceAndType(serviceName, typeName) +
                `\`${typeName}\` is an extension type, but \`${typeName}\` is not defined in any service`));
        }
    };
    return {
        ObjectTypeExtension: checkExtension,
        InterfaceTypeExtension: checkExtension,
    };
}
exports.PossibleTypeExtensions = PossibleTypeExtensions;
function typeToExtKind(type) {
    if (graphql_1.isScalarType(type)) {
        return graphql_1.Kind.SCALAR_TYPE_EXTENSION;
    }
    else if (graphql_1.isObjectType(type)) {
        return graphql_1.Kind.OBJECT_TYPE_EXTENSION;
    }
    else if (graphql_1.isInterfaceType(type)) {
        return graphql_1.Kind.INTERFACE_TYPE_EXTENSION;
    }
    else if (graphql_1.isUnionType(type)) {
        return graphql_1.Kind.UNION_TYPE_EXTENSION;
    }
    else if (graphql_1.isEnumType(type)) {
        return graphql_1.Kind.ENUM_TYPE_EXTENSION;
    }
    else if (graphql_1.isInputObjectType(type)) {
        return graphql_1.Kind.INPUT_OBJECT_TYPE_EXTENSION;
    }
    return null;
}
function typeToKind(type) {
    if (graphql_1.isScalarType(type)) {
        return graphql_1.Kind.SCALAR_TYPE_DEFINITION;
    }
    else if (graphql_1.isObjectType(type)) {
        return graphql_1.Kind.OBJECT_TYPE_DEFINITION;
    }
    else if (graphql_1.isInterfaceType(type)) {
        return graphql_1.Kind.INTERFACE_TYPE_DEFINITION;
    }
    else if (graphql_1.isUnionType(type)) {
        return graphql_1.Kind.UNION_TYPE_DEFINITION;
    }
    else if (graphql_1.isEnumType(type)) {
        return graphql_1.Kind.ENUM_TYPE_DEFINITION;
    }
    else if (graphql_1.isInputObjectType(type)) {
        return graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION;
    }
    return null;
}
//# sourceMappingURL=possibleTypeExtensions.js.map