const Encore = require("@symfony/webpack-encore");
const { resolve, parse } = require("path");
const {existsSync} = require("fs");
const { readdir } = require("fs").promises;

/**
 * get the file names inside given directory recursively, limiting to
 * a given depth in the recursion
 *
 * @param string  dir    the directory
 * @param int     depth  the maximum depth to look into
 */
async function* getFiles(dir, depth, ignored) {
  const dirents = await readdir(dir, { withFileTypes: true });
  for (const dirent of dirents) {
    const res = resolve(dir, dirent.name);
    if (dirent.isDirectory()) {
      if (depth > 0) {
        yield* getFiles(res, depth - 1, ignored);
      }
    } else if (ignored.includes(res)) {
      continue;
    } else {
      yield res;
    }
  }
}

/**
 * populate the config of encore in directories inside `'./src'` and
 * `'./vendor'` and letting them to alter the encore config.
 *
 * if a file `chill.webpack.config.js` is found, the default function is
 * imported and executed. This function receive two arguments:
 *
 * - `Encore`, the main encore object
 * - `chillEntries`: the entries which will be appended to the main `chill` module,
 * resulting in a chill.js and chill.css file.
 *
 */
async function populateConfig(Encore, chillEntries) {
  // chill-main contains some bootstrap that must be loaded first.
  // we register them first and, then, store this chill.webpack.config.js file
  // into `toIgnore`, ignoring it when we loop on other folders.
  let toIgnore = [];

  // loop into chill main
  for await (const f of getFiles("./src/Bundle/ChillMainBundle/", 1, [])) {
    let filename = parse(f).base;
    if (filename === "chill.webpack.config.js") {
      configure = require(f);
      configure(Encore, chillEntries);
      toIgnore.push(f);
    }
  }

  // loop into other chill bundles
  for await (const f of getFiles("./src/Bundle", 2, toIgnore)) {
    let filename = parse(f).base;
    if (filename === "chill.webpack.config.js") {
      configure = require(f);
      configure(Encore, chillEntries);
    }
  }
}

// export the final configuration
module.exports = (async () => {
  // Manually configure the runtime environment if not already configured yet by the "encore" command.
  // It's useful when you use tools that rely on webpack.config.js file.
  if (!Encore.isRuntimeEnvironmentConfigured()) {
    Encore.configureRuntimeEnvironment(process.env.NODE_ENV || "dev");
  }
  // basic encore configuration
  Encore.setOutputPath("public/build/")
    .setPublicPath("/build")
    .enableSassLoader(function (options) {
      // If set to true, Sass won’t print warnings that are caused by dependencies (like bootstrap):
      // https://sass-lang.com/documentation/js-api/interfaces/options/#quietDeps
        options.sassOptions.quietDeps = true;
        options.sassOptions.silenceDeprecations = ['import'];
    })
    .enableVueLoader(() => {}, {
      version: 3,
    })
    .enableTypeScriptLoader(function (tsConfig) {
      tsConfig.appendTsSuffixTo = [/\.vue$/];
      tsConfig.appendTsxSuffixTo = [/\.vue$/];
      // temporary fix for https://github.com/vuejs/vue-loader/issues/1915 and https://github.com/vuejs/core/issues/2855
      tsConfig.compilerOptions = { strict: !Encore.isProduction() };
      tsConfig.silent = false;
    })
    //.enableForkedTypeScriptTypesChecking()
    .autoProvidejQuery()
    .enableSourceMaps(!Encore.isProduction())
    .cleanupOutputBeforeBuild()
    //.enableBuildNotifications()
    .enableVersioning()
    .enableSingleRuntimeChunk()
    .splitEntryChunks();

  // populate config with chill entries
  let chillEntries = [];
  await populateConfig(Encore, chillEntries);

  Encore.addAliases({
    translator: resolve(__dirname, 'assets/translator.ts'),
    "@symfony/ux-translator": resolve(__dirname, './vendor/symfony/ux-translator/assets'),
  });

    //getting the encore config and appending chill entries
    config = Encore.getWebpackConfig();
    config.entry.chill = chillEntries;

  if (!Encore.isProduction()) {
    console.log(config);
    config.devtool = "eval-source-map";
  }

  return config;
})();
