"use strict";
// import { IBetterLogger, INTERFACES } from "@codiac.io/codiac-common";
// import { inject, injectable } from "inversify";
// const autocomplete = require("inquirer-autocomplete-prompt");
// import inquirer = require('inquirer');
// import fuzzy = require("fuzzy");
// import { INTERFACES_CLI, IOutputStyler, IUserInputProvider } from "../ops";
// import { PromptChoice } from "../cli-entities/prompt-choice";
// // private async searchPorts(answers: PromptChoice[], input: string): Promise<PromptChoice[]> {
// //   return new Promise<PromptChoice[]>(async (resolve, reject) => {
// //     try {
// //       // Whatever voodoo they're doing inside the autocomplete plugin,
// //       // they're redefining "this", so we cant use it here.
// //       // Great, we'll just HACK UP a fucking module scoped variable to hold onto the goddamn list then.
// //       // let vers = this.getVersions();
// //       input = input || "";
// //       setTimeout(() => {
// //         let filtered: PromptChoice[];
// //         // if (parseInt(input) != NaN) {
// //         if (isNaN(+input)) {
// //           // let options: fuzzy.FilterOptions<PromptChoice> = { extract: (ver: PromptChoice) => { return ver.value } };
// //           let options: fuzzy.FilterOptions<PromptChoice> = { extract: (ver: PromptChoice) => { return ver.name } };
// //           let results = fuzzy.filter(input, ports, options);
// //           filtered = results.map((fr: fuzzy.FilterResult<PromptChoice>) => fr.original);
// //         } else {
// //           filtered = ports.filter(p => `${p.value}`.startsWith(input))
// //         }
// //         resolve(filtered)
// //       }, 20); //_.random(30, 500));  // why a random number?
// //     } catch (err) {
// //       reject(err);
// //     }
// //   });
// // }
// export type ValidationResult = boolean | { isValid: boolean, reason?: string }
// type FuzzyResult = {
//   /** The rendered string (eg: '<b>lah'). */
//   string: string,
//   /** The index of the element in `arr` (eg: 2). */
//   index: number,
//   /** The original element in `arr`. */
//   original: 'blah'
// }
// /** Has to be module-scoped bc the autocomplete redefines "this",
//  *  so we can't use it inside getFuzzyFilteredChoices().
//  *
//  * THIS WILL PREVENT MULTIPLE instances of a fuzzy-search: Refactor to use `PromptSelectFuzzy.fetchedChoices[controlId]` instead.
//  */
// let fetchedChoices: PromptChoice[] = [];
// /** Prompt for a value using a fuzzy-search to show available selections.
//  */
// @injectable()
// export class PromptSelectFuzzy {
//   constructor(
//     @inject(INTERFACES.IBetterLogger) private logger: IBetterLogger,
//     @inject(INTERFACES_CLI.IUserInputProvider) private _ui: IUserInputProvider,
//     @inject(INTERFACES_CLI.IOutputStyler) private _styler: IOutputStyler
//   ) {
//   }
//   private static fetchedChoices: { [controlId: string]: PromptChoice[] } = {};
//   public go(controlId: string, prompt: string, suggestOnly: boolean, defaultValue: string | undefined, searchOnRemote: boolean, fetchMethod: (searchString?: string) => Promise<PromptChoice[]>, validationMethod?: ((candidate: string) => ValidationResult)): Promise<string> {
//     return new Promise<string>(async (resolve, reject) => {
//       let entry: string | undefined;  // = defaultValue;
//       try {
//         // TODO: Consider running this inside getFuzzyFilteredChoices()...
//         // eg:
//         // let fuzzySearch = (answers: PromptChoice[], input: string): Promise<PromptChoice[]> {
//         //  return this.getFuzzyFilteredChoices(answers, input, fetchMethod);
//         // }
//         // PromptSelectFuzzy.fetchedChoices[controlId] = await fetchMethod();
//         if (searchOnRemote !== true) fetchedChoices = await fetchMethod("");
//         let selectedValue: string | undefined;
//         let isValid: boolean = false;
//         let invalidReason: string | undefined;
//         while (entry === undefined || !isValid) {
//           inquirer.registerPrompt('autocomplete', autocomplete);
//           if (invalidReason) this._ui.userMessage(invalidReason);
//           let selectResult = await inquirer.prompt<{ [key: string]: string }>([{
//             type: 'autocomplete',
//             suggestOnly: suggestOnly,
//             name: controlId,
//             message: `${prompt} `,
//             source: (searchOnRemote) ? (answers: PromptChoice[], input: string) => fetchMethod(input) : this.getFuzzyFilteredChoices,
//             default: defaultValue
//           }]);
//           entry = selectResult[controlId];
//           selectedValue = selectResult[controlId];  // this is not entry because selectedValue should be of generic type "T"
//           this.logger.trace(`${controlId} selected`, selectedValue);
//           // Validate the selection
//           let validResult = (validationMethod) ? validationMethod(selectedValue) : true;
//           if (typeof validResult === 'boolean') {
//             isValid = validResult;
//             invalidReason = undefined;
//           } else {
//             isValid = validResult.isValid;
//             invalidReason = validResult.reason;
//           }
//           if (!isValid) {
//             this.logger.trace(`${controlId} value [${selectedValue}] is invalid. ${invalidReason ?? ""}`);
//           }
//         }
//         resolve(selectedValue ?? "");
//       } catch (err) {
//         this.logger.error(`Error performing a fuzzy-select for [${controlId}]: ${err.name ?? ""} ${err.message ?? ""}`, err.stack);
//         reject(err);
//       }
//     });
//   }
//   /** Performs the actual fuzzy-filtering of the already-fetched module-scoped list of available values.  */
//   private getFuzzyFilteredChoices(answers: PromptChoice[], input: string): Promise<PromptChoice[]> {
//     return new Promise<PromptChoice[]>(async (resolve, reject) => {
//       try {
//         // Whatever voodoo they're doing inside the autocomplete plugin,
//         // they're redefining "this", so we cant use it here.
//         // Great, we'll just HACK UP a fucking module scoped variable to hold onto the goddamn list then.
//         // let vers = this.getVersions();
//         input = input || "";
//         // Original instructions called for this (maybe to debounce it?)
//         // setTimeout(() => {
//         let filtered: PromptChoice[];
//         // if (parseInt(input) != NaN) {
//         if (isNaN(+input)) {
//           // let options: fuzzy.FilterOptions<PromptChoice> = { extract: (ver: PromptChoice) => { return ver.value } };
//           let options: fuzzy.FilterOptions<PromptChoice> = { extract: (ver: PromptChoice) => { return ver.name } };
//           let results = fuzzy.filter(input, fetchedChoices, options);
//           filtered = results.map((fr: fuzzy.FilterResult<PromptChoice>) => fr.original);
//         } else {
//           // Numeric search
//           filtered = fetchedChoices.filter(p => `${p.value}`.startsWith(input))
//         }
//         resolve(filtered)
//         // }, 20);  // is this for debouncing?
//       } catch (err) {
//         reject(err);
//       }
//     });
//   }
// }
//# sourceMappingURL=prompt-select-fuzzy.js.map