"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.applyPatchToFile = void 0;
const zod_1 = require("zod");
const utils_1 = require("../../../utils");
const utils_2 = require("./utils");
const diff_1 = require("diff");
const promises_1 = require("fs/promises");
const path_1 = __importDefault(require("path"));
const chalk_1 = __importDefault(require("chalk"));
// export const applyPatchesToFile = defineToolSpec({
//   name: "apply_multiple_patches_to_file",
//   description: `Apply multiple patches on a single file in a plugin's directory and get the result of applying the patch. The file paths 
//   should be provided relative to the plugin's directory. The file reading tools append line numbers in the format <line_number>:<space>. 
//   This prefix is not actually a part of the file and you should generate the patch as if the line number and the trailing 
//   colon and space after it were not there.`,
//   inputSchema: {
//     plugin_name: z.string().describe("Name of the plugin inside whose directory the target file will be looked for."),
//     file_path: z.string().describe("The relative path of the file within the plugin's directory to which the patch should be applied."),
//     apptile_context: apptileContextZodSchema,
//     patch: z.string().describe(`The patch to be applied. This should be a 'unified diff' in the format:
// @@ -line,count +line,count @@
// - old line
// + new line
// @@ -line,count +line,count @@
// - old line
// + new line
// `)
//   },
//   async cb(inputVars) {
//     logger.info("Running tool " + chalk.green("apply_multiple_patches_to_file"));
//     const result = await new Promise<string>(async (resolve) => {
//       try {
//         if (!inputVars.apptile_context?.plugins_dir) {
//           resolve("Error: apptile_context was not resolved in the system. Something went wrong!");
//         } else {
//           const fullFilePath = path.resolve(
//             inputVars.apptile_context.plugins_dir, 
//             inputVars.plugin_name, 
//             inputVars.file_path
//           );
//           let hasError = false;
//           let fileContents = await readFile(fullFilePath, "utf8");
//           applyPatches(inputVars.patch, {
//             loadFile: (patch, callback) => {
//                 callback(undefined, fileContents);
//             },
//             patched: (patch, patchedContent, callback) => {
//               if (patchedContent !== false) {
//                 fileContents = patchedContent;
//                 callback(null);
//               } else {
//                 hasError = true;
//                 callback("Error: `diff` returned false when calling applyPatch")
//               }
//             },
//             complete: async (err) => {
//               if (err) {
//                 resolve("Error: Failed to apply patch " + err);
//               } else {
//                 await writeFile(fullFilePath, fileContents);
//                 resolve("Patch applied successfully! ")
//               }
//             }
//           });
//         }
//       } catch (err) {
//         resolve("Error: Could not apply the patch: " + err);
//       }
//     });
//     return {
//       content: [{
//         type: "text",
//         text: result
//       }]
//     };
//   }
// })
exports.applyPatchToFile = (0, utils_2.defineToolSpec)({
    name: "apply_patch_to_file",
    description: `Apply patch on a file in a plugin's directory and get the result of applying the patch. The file paths 
  should be provided relative to the plugin's directory. The file reading tools append line numbers in the format <line_number>:<space>. 
  This prefix is not actually a part of the file and you should generate the patch as if the line number and the trailing 
  colon and space after it were not there.`,
    inputSchema: {
        plugin_name: zod_1.z.string().describe("Name of the plugin inside whose directory the target file will be looked for."),
        file_path: zod_1.z.string().describe("The relative path of the file within the plugin's directory to which the patch should be applied."),
        apptile_context: utils_1.apptileContextZodSchema,
        patch: zod_1.z.string().describe(`The patch to be applied. This should be a 'unified diff' in the format:
@@ -line,count +line,count @@
- old line
+ new line`)
    },
    cb(inputVars) {
        return __awaiter(this, void 0, void 0, function* () {
            utils_2.logger.info("Running tool: " + chalk_1.default.green("apply_patch_to_file"));
            const result = yield new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
                var _a;
                try {
                    if (!((_a = inputVars.apptile_context) === null || _a === void 0 ? void 0 : _a.plugins_dir)) {
                        resolve("Error: apptile_context was not resolved in the system. Something went wrong!");
                    }
                    else {
                        const fullFilePath = path_1.default.resolve(inputVars.apptile_context.plugins_dir, inputVars.plugin_name, inputVars.file_path);
                        const fileContents = yield (0, promises_1.readFile)(fullFilePath, "utf8");
                        const patchedContents = (0, diff_1.applyPatch)(fileContents, inputVars.patch, {
                            fuzzFactor: 3,
                            autoConvertLineEndings: true
                        });
                        if (patchedContents === false) {
                            resolve("Error: `diff` returned false when calling applyPatch.");
                        }
                        else {
                            yield (0, promises_1.writeFile)(fullFilePath, patchedContents);
                            resolve("Patch applied successfully!");
                        }
                    }
                }
                catch (err) {
                    resolve("Error: Could not apply the patch: " + err);
                }
            }));
            return {
                content: [{
                        type: "text",
                        text: result
                    }]
            };
        });
    }
});
