// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

// @ts-check
const path = require("path");
const process = require("process");
const { srcRoot } = require("./config");
const { getUncheckedLeafFiles, getAllEligibleFiles } = require("./eligible-file-finder");
const { getImportsForFile } = require("./import-finder");

if (process.argv.includes("--help")) {
  console.log("yarn null:find [--sort=name|count] [--show-count] [--filter file_path_substring]");
  process.exit(0);
}
const sortBy = process.argv.includes("--sort=name") ? "name" : "count";
const printDependedOnCount = process.argv.includes("--show-count");
const filterArgIndex = process.argv.indexOf("--filter") + 1;
const filterArg = filterArgIndex === 0 ? null : process.argv[filterArgIndex];
const filter = filterArg && ((file) => file.includes(filterArg));

async function main() {
  const eligibleFiles = await getUncheckedLeafFiles();

  const eligibleSet = new Set(eligibleFiles);

  const dependedOnCount = new Map(eligibleFiles.map((file) => [file, 0]));

  for (const file of await getAllEligibleFiles()) {
    if (eligibleSet.has(file)) {
      // Already added
      continue;
    }

    for (const imp of getImportsForFile(file, srcRoot)) {
      if (dependedOnCount.has(imp)) {
        dependedOnCount.set(imp, dependedOnCount.get(imp) + 1);
      }
    }
  }

  let out = Array.from(dependedOnCount.entries());
  if (filter) {
    out = out.filter((x) => filter(x[0]));
  }
  if (sortBy === "count") {
    out = out.sort((a, b) => b[1] - a[1]);
  } else if (sortBy === "name") {
    out = out.sort((a, b) => a[0].localeCompare(b[0]));
  }
  for (const pair of out) {
    console.log(toFormattedFilePath(pair[0]) + (printDependedOnCount ? ` — Depended on by **${pair[1]}** files` : ""));
  }
}

function toFormattedFilePath(file) {
  const relativePath = path.relative(srcRoot, file).replace(/\\/g, "/");
  return `"./src/${relativePath}",`;
}

main().catch((error) => {
  console.error(error.stack);
  process.exit(1);
});