"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OperationVariablesToObject = void 0;
const tslib_1 = require("tslib");
const auto_bind_1 = tslib_1.__importDefault(require("auto-bind"));
const graphql_1 = require("graphql");
const utils_js_1 = require("./utils.js");
class OperationVariablesToObject {
    constructor(_scalars, _convertName, _namespacedImportName = null, _enumNames = [], _enumPrefix = true, _enumSuffix = true, _enumValues = {}, _applyCoercion = false, _directiveArgumentAndInputFieldMappings = {}) {
        this._scalars = _scalars;
        this._convertName = _convertName;
        this._namespacedImportName = _namespacedImportName;
        this._enumNames = _enumNames;
        this._enumPrefix = _enumPrefix;
        this._enumSuffix = _enumSuffix;
        this._enumValues = _enumValues;
        this._applyCoercion = _applyCoercion;
        this._directiveArgumentAndInputFieldMappings = _directiveArgumentAndInputFieldMappings;
        (0, auto_bind_1.default)(this);
    }
    getName(node) {
        if (node.name) {
            if (typeof node.name === 'string') {
                return node.name;
            }
            return node.name.value;
        }
        if (node.variable) {
            return node.variable.name.value;
        }
        return null;
    }
    transform(variablesNode) {
        if (!variablesNode || variablesNode.length === 0) {
            return null;
        }
        return (variablesNode.map(variable => (0, utils_js_1.indent)(this.transformVariable(variable))).join(`${this.getPunctuation()}\n`) +
            this.getPunctuation());
    }
    getScalar(name) {
        const prefix = this._namespacedImportName ? `${this._namespacedImportName}.` : '';
        return `${prefix}Scalars['${name}']['input']`;
    }
    getDirectiveMapping(name) {
        return `DirectiveArgumentAndInputFieldMappings['${name}']`;
    }
    getDirectiveOverrideType(directives) {
        if (!this._directiveArgumentAndInputFieldMappings)
            return null;
        const type = directives
            .map(directive => {
            const directiveName = directive.name.value;
            if (this._directiveArgumentAndInputFieldMappings[directiveName]) {
                return this.getDirectiveMapping(directiveName);
            }
            return null;
        })
            .reverse()
            .find(a => !!a);
        return type || null;
    }
    transformVariable(variable) {
        let typeValue = null;
        const prefix = this._namespacedImportName ? `${this._namespacedImportName}.` : '';
        if (typeof variable.type === 'string') {
            typeValue = variable.type;
        }
        else {
            const baseType = (0, utils_js_1.getBaseTypeNode)(variable.type);
            const overrideType = variable.directives ? this.getDirectiveOverrideType(variable.directives) : null;
            const typeName = baseType.name.value;
            if (overrideType) {
                typeValue = overrideType;
            }
            else if (this._scalars[typeName]) {
                typeValue = this.getScalar(typeName);
            }
            else if (this._enumValues[typeName]?.sourceFile) {
                typeValue = this._enumValues[typeName].typeIdentifier || this._enumValues[typeName].sourceIdentifier;
            }
            else {
                typeValue = `${prefix}${this._convertName(baseType, {
                    useTypesPrefix: this._enumNames.includes(typeName) ? this._enumPrefix : true,
                    useTypesSuffix: this._enumNames.includes(typeName) ? this._enumSuffix : true,
                })}`;
            }
        }
        const fieldName = this.getName(variable);
        const fieldType = this.wrapAstTypeWithModifiers(typeValue, variable.type, this._applyCoercion);
        const hasDefaultValue = variable.defaultValue != null && typeof variable.defaultValue !== 'undefined';
        const isNonNullType = variable.type.kind === graphql_1.Kind.NON_NULL_TYPE;
        const formattedFieldString = this.formatFieldString(fieldName, isNonNullType, hasDefaultValue);
        const formattedTypeString = this.formatTypeString(fieldType, isNonNullType, hasDefaultValue);
        return `${formattedFieldString}: ${formattedTypeString}`;
    }
    wrapAstTypeWithModifiers(_baseType, _typeNode, _applyCoercion) {
        throw new Error(`You must override "wrapAstTypeWithModifiers" of OperationVariablesToObject!`);
    }
    formatFieldString(fieldName, _isNonNullType, _hasDefaultValue) {
        return fieldName;
    }
    formatTypeString(fieldType, isNonNullType, hasDefaultValue) {
        const prefix = this._namespacedImportName ? `${this._namespacedImportName}.` : '';
        if (hasDefaultValue) {
            return `${prefix}Maybe<${fieldType}>`;
        }
        return fieldType;
    }
    getPunctuation() {
        return ',';
    }
}
exports.OperationVariablesToObject = OperationVariablesToObject;
