// Decompile selected function recursively (until a given number of new functions is reached)
// @category _Reman3
// @menupath Reman3.Dump N Functions

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import ghidra.app.script.GhidraScript;
import ghidra.pcodeCPort.address.Address;
import ghidra.program.model.listing.Function;
import re3lib.FunctionDatabase;
import re3lib.FunctionDumper;
import re3lib.GlobalDumper;
import re3lib.PCallTracer;
import re3lib.RemanConfig;
import re3lib.TypeDumper;

public class DumpCurrentFunctionN extends GhidraScript {
  final int NumFunctions = 8;

  // class Entry {
  // Function function;
  // }
  // class QueueEntry {
  // Function function;
  // List<Function> callees;
  // }

  // HashSet<Address> visited = new HashSet<>();

  // QueueEntry enter(Function function) {
  // if (visited.contains(function.getEntryPoint()))
  // return null;

  // visited.add(function.getEntryPoint());

  // QueueEntry entry = new QueueEntry();
  // entry.function = function;

  // function.getCalledFunctions(monitor);

  // }

  @Override
  public void run() throws Exception {
    RemanConfig.INSTANCE = new RemanConfig(this);
    RemanConfig.INSTANCE.createDirectories();

    try (FunctionDatabase functionDatabase = new FunctionDatabase(this)) {

      GlobalDumper globalDumper = new GlobalDumper(this, functionDatabase);
      globalDumper.loadGlobalManifest();

      FunctionDumper functionDumper = new FunctionDumper(this, functionDatabase, globalDumper);

      PCallTracer tracer = new PCallTracer();
      tracer.setBlacklist(functionDumper.functionAddrBlackList);
      tracer.traceCalls(getFunctionContaining(currentAddress));

      List<Address> queue = new ArrayList<>();

      // List<Function> functionsToDump = new ArrayList<>();
      // List<Function> functionsToDumpNew = new ArrayList<>();
      // for (Function func : tracer.out) {
      // if (FunctionDumper.isDumpedFix(func))
      // continue;

      // println("Dump: " + func.getName());
      // functionsToDump.add(func);

      // if (!FunctionDumper.isDumpedAuto(func))
      // functionsToDumpNew.add(func);
      // }

      // if (!functionsToDump.isEmpty()) {
      // String newOpt = "Only new (" + functionsToDumpNew.size() + ")";
      // String okOpt = "Yes (" + functionsToDump.size() + ")";
      // String choice = askChoice("Confirmation", "About to generate " +
      // functionsToDump.size() + " functions ("
      // + functionsToDumpNew.size() + " new), continue?",
      // new ArrayList<String>() {
      // {
      // add(okOpt);
      // add(newOpt);
      // add("No");
      // }
      // }, okOpt);
      // if (choice == okOpt) {
      // } else if (choice == newOpt) {
      // functionsToDump = functionsToDumpNew;
      // } else {
      // return;
      // }

      // for (Function func : functionsToDump) {
      // functionDumper.dump(func);
      // }

      // if (functionDumper.createdFile)
      // RecompileConfig.INSTANCE.touchCMakeTimestamp();

      // globalDumper.dumpGlobals();
      // globalDumper.saveGlobalManifest();
      // }

      // // Dump types
      // TypeDumper dumper = new TypeDumper(this);
      // dumper.run();
    }
  }
}
