import { serializePropertyRef } from "../refs.js";
import { createShape, shapeToPropertySchema } from "../schema-util.js";
import { getVariablesSchema } from "../util/graphql-string.js";
import { pickObjectSchema } from "../util/merge.js";
const defaultParameters = {
    type: 'object',
    properties: {}
};
Object.freeze(defaultParameters);
class ToolImpl {
    #schema;
    #tool;
    #ref;
    #execution;
    constructor(parent, ref, json) {
        this.#schema = parent;
        this.#ref = ref;
        this.#tool = json;
        if (this.#tool.execution.type === 'remote') {
            this.#execution = new ToolExecutionRemoteImpl(this.#schema, this.#tool.execution);
        }
        else {
            this.#execution = new ToolExecutionGraphQLImpl(this.#schema, this.#tool.execution);
        }
    }
    get name() {
        return this.#tool.name;
    }
    get description() {
        if (this.#tool.description) {
            return this.#tool.description;
        }
        if (this.#execution.type === 'graphql') {
            return this.#execution.getQueryDescription();
        }
        return undefined;
    }
    get json() {
        return this.#tool;
    }
    get execution() {
        return this.#execution;
    }
    get ref() {
        return serializePropertyRef(this.#ref);
    }
    get refItem() {
        return this.#ref;
    }
    get parametersSchema() {
        if (this.#execution.type === 'graphql') {
            const getQueryArgSchemaResult = this.#execution.getQueryArgSchema();
            return getQueryArgSchemaResult?.argsSchema ?? defaultParameters;
        }
        return defaultParameters;
    }
}
class ToolExecutionGraphQLImpl {
    #schema;
    #execution;
    type;
    constructor(schema, execution) {
        this.#schema = schema;
        this.#execution = execution;
        this.type = 'graphql';
    }
    get path() {
        return this.#execution.path;
    }
    get optimizeResponse() {
        return this.#execution.optimizeResponse;
    }
    getGraphQLParams(queryGenerator) {
        const { query } = this.#execution;
        const source = typeof query === 'string'
            ? query
            : queryGenerator(this.#schema, {
                selectionSet: query.selectionSet,
                query: this.#schema.ensureQuery(query.ref)
            });
        return { source: source };
    }
    getQueryArgSchema() {
        const { query } = this.#execution;
        if (typeof query === 'string') {
            const result = getVariablesSchema(this.#schema, query);
            if (!result) {
                return;
            }
            return result;
        }
        let { argsSchema, argsAreFromShape } = this.#schema.ensureQuery(query.ref);
        if (argsSchema && query.args) {
            argsSchema = pickObjectSchema(argsSchema, query.args);
        }
        const argSchemaResult = argsSchema && shapeToPropertySchema(this.#schema.json, createShape('Args', argsSchema));
        if (argSchemaResult) {
            return {
                argsSchema: argSchemaResult,
                argsAreFromShape
            };
        }
    }
    getQueryDescription() {
        const { query } = this.#execution;
        if (typeof query === 'object') {
            return this.#schema.ensureQuery(query.ref).json.description;
        }
    }
}
class ToolExecutionRemoteImpl {
    #schema;
    #execution;
    type;
    constructor(schema, execution) {
        this.#schema = schema;
        this.#execution = execution;
        this.type = 'remote';
    }
    get service() {
        return this.#execution.service;
    }
    get toolName() {
        return this.#execution.toolName;
    }
}
export function createTool(parent, ref, entry) {
    return new ToolImpl(parent, ref, entry);
}
// class ToolExecutionMemoryImpl implements ToolExecutionMemory {
//   #schema: ProjectSchema;
//   #execution: ToolExecutionMemoryJSON;
//   type: 'memory';
//   getArgSchema() {
//     const args = this.#execution.args;
//     if (!args) {
//       return undefined;
//     }
//     const argsShape = this.#schema.getShape(args);
//     if (!argsShape) {
//       return undefined;
//     }
//     return shapeToPropertySchema(this.#schema.json, argsShape.json) as ObjectSchema;
//   }
//   constructor(schema: ProjectSchema, execution: ToolExecutionMemoryJSON) {
//     this.#schema = schema;
//     this.#execution = execution;
//     this.type = 'memory';
//   }
// }
