// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview Script mutator.
 */

'use strict';

const fs = require('fs');
const path = require('path');

const common = require('./mutators/common.js');
const db = require('./db.js');
const sourceHelpers = require('./source_helpers.js');

const { AddTryCatchMutator } = require('./mutators/try_catch.js');
const { ArrayMutator } = require('./mutators/array_mutator.js');
const { CrossOverMutator } = require('./mutators/crossover_mutator.js');
const { ExpressionMutator } = require('./mutators/expression_mutator.js');
const { FunctionCallMutator } = require('./mutators/function_call_mutator.js');
const { IdentifierNormalizer } = require('./mutators/normalizer.js');
const { NumberMutator } = require('./mutators/number_mutator.js');
const { ObjectMutator } = require('./mutators/object_mutator.js');
const { VariableMutator } = require('./mutators/variable_mutator.js');
const { VariableOrObjectMutator } = require('./mutators/variable_or_object_mutation.js');

function defaultSettings() {
  return {
    ADD_VAR_OR_OBJ_MUTATIONS: 0.1,
    DIFF_FUZZ_EXTRA_PRINT: 0.1,
    DIFF_FUZZ_TRACK_CAUGHT: 0.4,
    MUTATE_ARRAYS: 0.1,
    MUTATE_CROSSOVER_INSERT: 0.05,
    MUTATE_EXPRESSIONS: 0.1,
    MUTATE_FUNCTION_CALLS: 0.1,
    MUTATE_NUMBERS: 0.05,
    MUTATE_OBJECTS: 0.1,
    MUTATE_VARIABLES: 0.075,
  };
}

class Result {
  constructor(code, flags) {
    this.code = code;
    this.flags = flags;
  }
}

class ScriptMutator {
  constructor(settings, db_path=undefined) {
    // Use process.cwd() to bypass pkg's snapshot filesystem.
    this.mutateDb = new db.MutateDb(db_path || path.join(process.cwd(), 'db'));
    this.mutators = [
      new ArrayMutator(settings),
      new ObjectMutator(settings),
      new VariableMutator(settings),
      new NumberMutator(settings),
      new CrossOverMutator(settings, this.mutateDb),
      new ExpressionMutator(settings),
      new FunctionCallMutator(settings),
      new VariableOrObjectMutator(settings),
      new AddTryCatchMutator(settings),
    ];
  }

  _addMjsunitIfNeeded(dependencies, input) {
    if (dependencies.has('mjsunit')) {
      return;
    }

    if (!input.absPath.includes('mjsunit')) {
      return;
    }

    // Find mjsunit.js
    let mjsunitPath = input.absPath;
    while (path.dirname(mjsunitPath) != mjsunitPath &&
           path.basename(mjsunitPath) != 'mjsunit') {
      mjsunitPath = path.dirname(mjsunitPath);
    }

    if (path.basename(mjsunitPath) == 'mjsunit') {
      mjsunitPath = path.join(mjsunitPath, 'mjsunit.js');
      dependencies.set('mjsunit', sourceHelpers.loadDependencyAbs(
          input.baseDir, mjsunitPath));
      return;
    }

    console.log('ERROR: Failed to find mjsunit.js');
  }

  _addSpiderMonkeyShellIfNeeded(dependencies, input) {
    // Find shell.js files
    const shellJsPaths = new Array();
    let currentDir = path.dirname(input.absPath);

    while (path.dirname(currentDir) != currentDir) {
      const shellJsPath = path.join(currentDir, 'shell.js');
      if (fs.existsSync(shellJsPath)) {
         shellJsPaths.push(shellJsPath);
      }

      if (currentDir == 'spidermonkey') {
        break;
      }
      currentDir = path.dirname(currentDir);
    }

    // Add shell.js dependencies in reverse to add ones that are higher up in
    // the directory tree first.
    for (let i = shellJsPaths.length - 1; i >= 0; i--) {
      if (!dependencies.has(shellJsPaths[i])) {
        const dependency = sourceHelpers.loadDependencyAbs(
            input.baseDir, shellJsPaths[i]);
        dependencies.set(shellJsPaths[i], dependency);
      }
    }
  }

  _addJSTestStubsIfNeeded(dependencies, input) {
    if (dependencies.has('jstest_stubs') ||
        !input.absPath.includes('JSTests')) {
      return;
    }
    dependencies.set(
        'jstest_stubs', sourceHelpers.loadResource('jstest_stubs.js'));
  }

  mutate(source) {
    for (const mutator of this.mutators) {
      mutator.mutate(source);
    }
  }

  // Returns parsed dependencies for inputs.
  resolveInputDependencies(inputs) {
    const dependencies = new Map();

    // Resolve test harness files.
    inputs.forEach(input => {
      try {
        // TODO(machenbach): Some harness files contain load expressions
        // that are not recursively resolved. We already remove them, but we
        // also need to load the dependencies they point to.
        this._addJSTestStubsIfNeeded(dependencies, input);
        this._addMjsunitIfNeeded(dependencies, input)
        this._addSpiderMonkeyShellIfNeeded(dependencies, input);
      } catch (e) {
        console.log(
            'ERROR: Failed to resolve test harness for', input.relPath);
        throw e;
      }
    });

    // Resolve dependencies loaded within the input files.
    inputs.forEach(input => {
      try {
        input.loadDependencies(dependencies);
      } catch (e) {
        console.log(
            'ERROR: Failed to resolve dependencies for', input.relPath);
        throw e;
      }
    });

    // Map.values() returns values in insertion order.
    return Array.from(dependencies.values());
  }

  // Combines input dependencies with fuzzer resources.
  resolveDependencies(inputs) {
    const dependencies = this.resolveInputDependencies(inputs);

    // Add stubs for non-standard functions in the beginning.
    dependencies.unshift(sourceHelpers.loadResource('stubs.js'));

    // Add our fuzzing support helpers. This also overrides some common test
    // functions from earlier dependencies that cause early bailouts.
    dependencies.push(sourceHelpers.loadResource('fuzz_library.js'));

    return dependencies;
  }

  // Normalizes, combines and mutates multiple inputs.
  mutateInputs(inputs) {
    const normalizerMutator = new IdentifierNormalizer();

    for (const [index, input] of inputs.entries()) {
      try {
        normalizerMutator.mutate(input);
      } catch (e) {
        console.log('ERROR: Failed to normalize ', input.relPath);
        throw e;
      }

      common.setSourceLoc(input, index, inputs.length);
    }

    // Combine ASTs into one. This is so that mutations have more context to
    // cross over content between ASTs (e.g. variables).
    const combinedSource = common.concatPrograms(inputs);
    this.mutate(combinedSource);

    return combinedSource;
  }

  mutateMultiple(inputs) {
    // High level operation:
    // 1) Compute dependencies from inputs.
    // 2) Normalize, combine and mutate inputs.
    // 3) Generate code with dependency code prepended.
    const dependencies = this.resolveDependencies(inputs);
    const combinedSource = this.mutateInputs(inputs);
    const code = sourceHelpers.generateCode(combinedSource, dependencies);
    const flags = common.concatFlags(dependencies.concat([combinedSource]));
    return new Result(code, flags);
  }
}

module.exports = {
  defaultSettings: defaultSettings,
  ScriptMutator: ScriptMutator,
};
