// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import childProcess from 'node:child_process';
import fs from 'node:fs/promises';
import path from 'node:path';
import {performance} from 'node:perf_hooks';

import {
  autoninjaPyPath,
  gnPyPath,
  isInChromiumDirectory,
  rootPath,
  vpython3ExecutablePath,
} from './devtools_paths.js';

/**
 * Errors returned from `spawn()` will have additional `stderr` and `stdout`
 * properties, similar to what we'd get from `child_process.execFile()`.
 */
class SpawnError extends Error {
  /**
   * Constructor for errors generated from `spawn()`.
   *
   * @param {string} message The actual error message.
   * @param {string} stderr The child process' error output.
   * @param {string} stdout The child process' regular output.
   */
  constructor(message, stderr, stdout) {
    super(message);
    this.stderr = stderr;
    this.stdout = stdout;
  }
}

/**
 * Promisified wrapper around `child_process.spawn()`.
 *
 * In addition to forwarding the `options` to `child_process.spawn()`, it'll also
 * set the `shell` option to `true`, to ensure that on Windows we can correctly
 * invoke `.bat` files (necessary for the Python3 wrapper script).
 *
 * @param {string} command The command to run.
 * @param {Array<string>} args List of string arguments to pass to the `command`.
 * @param {Object} options Passed directly to `child_process.spawn()`.
 * @returns {Promise<{stdout: string, stderr: string}>}
 */
function spawn(command, args, options = {}) {
  return new Promise((resolve, reject) => {
    const child = childProcess.spawn(command, args, {
      ...options,
      shell: true,
    });

    let stdout = '';
    let stderr = '';

    child.stdout.on('data', data => {
      stdout += data.toString();
    });

    child.stderr.on('data', data => {
      stderr += data.toString();
    });

    child.on('exit', (code, signal) => {
      if (signal) {
        reject(
            new SpawnError(
                `Process terminated due to signal ${signal}`,
                stderr,
                stdout,
                ),
        );
      } else if (code) {
        reject(
            new SpawnError(`Process exited with code ${code}`, stderr, stdout),
        );
      } else {
        resolve({stdout, stderr});
      }
    });

    child.on('error', reject);
  });
}

/**
 * Representation of the feature set that is configured for Chrome. This
 * keeps track of enabled and disabled features and generates the correct
 * combination of `--enable-features` / `--disable-features` command line
 * flags.
 *
 * There are unit tests for this in `./devtools_build.test.mjs`.
 */
export class FeatureSet {
  #disabled = new Set();
  #enabled = new Map();

  /**
   * Disables the given `feature`.
   *
   * @param feature the name of the feature to disable.
   */
  disable(feature) {
    this.#disabled.add(feature);
    this.#enabled.delete(feature);
  }

  /**
   * Enables the given `feature`, and optionally adds the `parameters` to it.
   * For example:
   * ```js
   * featureSet.enable('DevToolsFreestyler', {patching: true});
   * ```
   * The parameters are additive.
   *
   * @param feature the name of the feature to enable.
   * @param parameters the additional parameters to pass to it, in
   *                            the form of key/value pairs.
   */
  enable(feature, parameters = {}) {
    this.#disabled.delete(feature);
    if (!this.#enabled.has(feature)) {
      this.#enabled.set(feature, Object.create(null));
    }
    for (const [key, value] of Object.entries(parameters)) {
      this.#enabled.get(feature)[key] = value;
    }
  }

  /**
   * Merge the other `featureSet` into this.
   *
   * @param featureSet the other `FeatureSet` to apply.
   */
  merge(featureSet) {
    for (const feature of featureSet.#disabled) {
      this.disable(feature);
    }
    for (const [feature, parameters] of featureSet.#enabled) {
      this.enable(feature, parameters);
    }
  }

  /**
   * Yields the command line parameters to pass to the invocation of
   * a Chrome binary for achieving the state of the feature set.
   */
  * [Symbol.iterator]() {
    const disabledFeatures = [...this.#disabled];
    if (disabledFeatures.length) {
      yield `--disable-features=${disabledFeatures.sort().join(',')}`;
    }
    const enabledFeatures = [...this.#enabled].map(([feature, parameters]) => {
      parameters = Object.entries(parameters);
      if (parameters.length) {
        parameters = parameters.map(([key, value]) => `${key}/${value}`);
        feature = `${feature}:${parameters.sort().join('/')}`;
      }
      return feature;
    });
    if (enabledFeatures.length) {
      yield `--enable-features=${enabledFeatures.sort().join(',')}`;
    }
  }

  static parse(text) {
    if (!text) {
      return [];
    }
    const features = [];
    for (const str of text.split(',')) {
      const parts = str.split(':');
      if (parts.length < 1 || parts.length > 2) {
        throw new Error(`Invalid feature declaration '${str}'`);
      }
      const feature = parts[0];
      const parameters = Object.create(null);
      if (parts.length > 1) {
        const args = parts[1].split('/');
        if (args.length % 2 !== 0) {
          throw new Error(
              `Invalid parameters '${parts[1]}' for feature ${feature}`,
          );
        }
        for (let i = 0; i < args.length; i += 2) {
          const key = args[i + 0];
          const value = args[i + 1];
          parameters[key] = value;
        }
      }
      features.push({feature, parameters});
    }
    return features;
  }
}

/**
 * Constructs a human readable error message for the given build `error`.
 *
 * @param error the `Error` from the failed `autoninja` invocation.
 * @param outDir the absolute path to the `target` out directory.
 * @param target the target relative to `//out`.
 * @returns the human readable error message.
 */
function buildErrorMessageForNinja(error, outDir, target) {
  const {message, stderr, stdout} = error;
  if (stderr) {
    // Anything that went to stderr has precedence.
    return `Failed to build \`${target}' in \`${outDir}'
${stdout}
${stderr}
`;
  }
  if (stdout) {
    // Check for `tsc` or `esbuild` errors in the stdout.
    const tscErrors = [
      ...stdout.matchAll(/^[^\s].*\(\d+,\d+\): error TS\d+:\s+.*$/gm),
    ].map(([tscError]) => tscError);
    if (!tscErrors.length) {
      // We didn't find any `tsc` errors, but maybe there are `esbuild` errors.
      // Transform these into the `tsc` format (with a made up error code), so
      // we can report all TypeScript errors consistently in `tsc` format (which
      // is well-known and understood by tools).
      const esbuildErrors = stdout.matchAll(
          /^✘ \[ERROR\] ([^\n]+)\n\n\s+\.\.\/\.\.\/(.+):(\d+):(\d+):/gm,
      );
      for (const [, message, filename, line, column] of esbuildErrors) {
        tscErrors.push(
            `${filename}(${line},${column}): error TS0000: ${message}`,
        );
      }
    }
    if (tscErrors.length) {
      return `TypeScript compilation failed for \`${target}'

${tscErrors.join('\n')}
`;
    }

    // At the very least we strip `ninja: Something, something` lines from the
    // standard output, since that's not particularly helpful.
    const output = stdout.replaceAll(/^ninja: [^\n]+\n+/gm, '').trim();
    return `Failed to build \`${target}' in \`${outDir}'

${output}
`;
  }
  return `Failed to build \`${target}' in \`${outDir}' (${message})`;
}

/** @enum */
export const BuildStep = {
  GN: 'gn',
  AUTONINJA: 'autoninja',
};

export class BuildError extends Error {
  /**
   * Constructs a new `BuildError` with the given parameters.
   *
   * @param step the build step that failed.
   * @param {object} options additional options for the `BuildError`.
   * @param options.cause the actual cause for the build error.
   * @param options.outDir the absolute path to the `target` out directory.
   * @param options.target the target relative to `//out`.
   */
  constructor(step, options) {
    const {cause, outDir, target} = options;
    const message = step === BuildStep.GN ? `\`gn' failed to initialize out directory ${outDir}` :
                                            buildErrorMessageForNinja(cause, outDir, target);
    super(message, {cause});
    this.step = step;
    this.name = 'BuildError';
    this.target = target;
    this.outDir = outDir;
  }
}

/**
 * @typedef BuildResult
 * @type {object}
 * @property {number} time - wall clock time (in seconds) for the build.
 */

/**
 * @param target the target relative to `//out`.
 * @returns the GN args for the `target`.
 */
export async function prepareBuild(target) {
  const outDir = path.join(rootPath(), 'out', target);

  // Prepare the build directory first.
  const outDirStat = await fs.stat(outDir).catch(() => null);
  if (!outDirStat?.isDirectory()) {
    // Use GN to (optionally create and) initialize the |outDir|.
    try {
      const gnExe = vpython3ExecutablePath();
      const gnArgs = [gnPyPath(), '-q', 'gen', outDir];
      await spawn(gnExe, gnArgs);
    } catch (cause) {
      throw new BuildError(BuildStep.GN, {cause, outDir, target});
    }
  }

  return await gnArgsForTarget(target);
}

/** @type Map<string, Promise<Map<string, string>>> */
const gnArgsCache = new Map();

/**
 * @param {string} target
 */
export function gnArgsForTarget(target) {
  let gnArgs = gnArgsCache.get(target);
  if (!gnArgs) {
    gnArgs = (async () => {
      const outDir = path.join(rootPath(), 'out', target);
      try {
        const cwd = rootPath();
        const gnExe = vpython3ExecutablePath();
        const gnArgs = [
          gnPyPath(),
          '-q',
          'args',
          outDir,
          '--json',
          '--list',
          '--short',
        ];
        const {stdout} = await spawn(gnExe, gnArgs, {cwd});
        return new Map(
            JSON.parse(stdout).map(
                arg =>
                    [arg.name,
                     arg.current?.value ?? arg.default?.value,
        ]),
        );
      } catch {
        return new Map();
      }
    })();
    gnArgsCache.set(target, gnArgs);
  }
  return gnArgs;
}

/** @type Map<string, Map<string, Promise<Array<string>>>> */
const gnRefsCache = new Map();

function gnRefsForTarget(target, filename) {
  let gnRefsPerTarget = gnRefsCache.get(target);
  if (!gnRefsPerTarget) {
    gnRefsPerTarget = new Map();
    gnRefsCache.set(target, gnRefsPerTarget);
  }
  let gnRef = gnRefsPerTarget.get(filename);
  if (!gnRef) {
    gnRef = (async () => {
      const cwd = rootPath();
      const outDir = path.join(rootPath(), 'out', target);
      const gnExe = vpython3ExecutablePath();
      const gnArgs = [gnPyPath(), 'refs', outDir, '--as=output', filename];
      const {stdout} = await spawn(gnExe, gnArgs, {cwd});
      return stdout.trim().split('\n');
    })();
    gnRefsPerTarget.set(filename, gnRef);
  }
  return gnRef;
}

/**
 *
 * @param {string} target
 * @param {string[]=} filenames
 * @returns {Promise<string[]>}
 */
async function computeBuildTargetsForFiles(target, filenames) {
  const SUPPORTED_EXTENSIONS = ['.css', '.ts'];
  if (filenames && filenames.length &&
      filenames.every(
          filename => SUPPORTED_EXTENSIONS.includes(path.extname(filename)),
          )) {
    if (isInChromiumDirectory().isInChromium) {
      filenames = filenames.map(
          filename => path.join('third_party', 'devtools-frontend', 'src', filename),
      );
    }
    const gnArgs = await gnArgsForTarget(target);
    if (gnArgs.get('devtools_bundle') === 'false') {
      try {
        const gnRefs = (await Promise.all(
                            filenames.map(filename => gnRefsForTarget(target, filename)),
                            ))
                           .flat();
        if (gnRefs.length) {
          // If there are any changes to TypeScript files, we need to also rebuild the
          // `en-US.json`, as otherwise the changes to `UIStrings` aren't picked up.
          if (filenames.some(filename => path.extname(filename) === '.ts')) {
            gnRefs.push('collect_strings');
          }
          return gnRefs;
        }
      } catch (error) {
        console.error(error);
      }
    }
  }

  return ['devtools_all_files'];
}

/**
 * @param {string} target
 * @param {{ filenames?: string[], signal?: AbortSignal}} options
 * @returns a `BuildResult` with statistics for the build.
 */
export async function build(target, options = {}) {
  const startTime = performance.now();
  const outDir = path.join(rootPath(), 'out', target);

  // Build just the devtools-frontend resources in |outDir|. This is important
  // since we might be running in a full Chromium checkout and certainly don't
  // want to build all of Chromium first.
  const buildTargets = await computeBuildTargetsForFiles(
      target,
      options.filenames,
  );
  try {
    const autoninjaExe = vpython3ExecutablePath();
    const autoninjaArgs = [autoninjaPyPath(), '-C', outDir, ...buildTargets];
    await spawn(autoninjaExe, autoninjaArgs, {
      shell: true,
      signal: options.signal,
    });
  } catch (cause) {
    if (cause.name === 'AbortError') {
      throw cause;
    }
    throw new BuildError(BuildStep.AUTONINJA, {cause, outDir, target});
  }

  // Report the build result.
  const time = (performance.now() - startTime) / 1000;
  return {time};
}
