/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import * as queue from "./queue";
import path from 'path'
import fs from 'fs'
import intersect from "intersect";
import parse_args from "minimist";
import util from "util";
import child_process from 'child_process';

let execFile = util.promisify(child_process.execFile);

function parseOptions(opts) {
  opts = parse_args(opts.split(/\s+/), {
    default: {build: "do", platform: "all", unittests: "none", tools: "none"},
    alias: {b: "build", p: "platform", u: "unittests", t: "tools", e: "extra-builds"},
    string: ["build", "platform", "unittests", "tools", "extra-builds"]
  });

  // Parse build types (d=debug, o=opt).
  let builds = intersect(opts.build.split(""), ["d", "o"]);

  // If the given value is nonsense default to debug and opt builds.
  if (builds.length == 0) {
    builds = ["d", "o"];
  }

  // Parse platforms.
  let allPlatforms = ["linux", "linux64", "linux64-asan", "linux64-fips",
                      "win", "win64", "win-make", "win64-make",
                      "linux64-make", "linux-make", "linux-fuzz",
                      "linux64-fuzz", "aarch64", "aarch64-make", "mac"];
  let platforms = intersect(opts.platform.split(/\s*,\s*/), allPlatforms);

  // If the given value is nonsense or "none" default to all platforms.
  if (platforms.length == 0 && opts.platform != "none") {
    platforms = allPlatforms;
  }

  // Parse unit tests.
  let aliases = {"gtests": "gtest"};
  let allUnitTests = ["bogo", "crmf", "chains", "cipher", "db", "ec", "fips",
                      "gtest", "interop", "lowhash", "merge", "sdr", "smime", "tools",
                      "ssl", "mpi", "scert", "spki", "policy", "tlsfuzzer"];
  let unittests = intersect(opts.unittests.split(/\s*,\s*/).map(t => {
    return aliases[t] || t;
  }), allUnitTests);

  // If the given value is "all" run all tests.
  // If it's nonsense then don't run any tests.
  if (opts.unittests == "all") {
    unittests = allUnitTests;
  } else if (unittests.length == 0) {
    unittests = [];
  }

  // Parse tools.
  let allTools = ["clang-format", "scan-build", "hacl", "saw", "abi", "coverage"];
  let tools = intersect(opts.tools.split(/\s*,\s*/), allTools);

  // If the given value is "all" run all tools.
  // If it's nonsense then don't run any tools.
  if (opts.tools == "all") {
    tools = allTools;
  } else if (tools.length == 0) {
    tools = [];
  }

  return {
    builds: builds,
    platforms: platforms,
    unittests: unittests,
    extra: (opts.e == "all"),
    tools: tools
  };
}

function filter(opts) {
  return function (task) {
    // Filter tools. We can immediately return here as those
    // are not affected by platform or build type selectors.
    if (task.platform == "nss-tools") {
      return opts.tools.some(tool => {
        return task.symbol.toLowerCase().startsWith(tool) ||
               (task.group && task.group.toLowerCase().startsWith(tool));
      });
    }

    // Filter unit tests.
    if (task.tests) {
      let found = opts.unittests.some(test => {
        if (task.group && task.group.toLowerCase() == "ssl" && test == "ssl") {
          return true;
        }
        if (task.group && task.group.toLowerCase() == "cipher" && test == "cipher") {
          return true;
        }
        return task.symbol.toLowerCase().startsWith(test);
      });

      if (!found) {
        return false;
      }
    }

    // Filter extra builds.
    if (task.group == "Builds" && !opts.extra) {
      return false;
    }

    let coll = name => name == (task.collection || "opt");

    // Filter by platform.
    let found = opts.platforms.some(platform => {
      let aliases = {
        "aarch64-make": "aarch64",
        "linux": "linux32",
        "linux-fuzz": "linux32",
        "linux64-asan": "linux64",
        "linux64-fips": "linux64",
        "linux64-fuzz": "linux64",
        "linux64-make": "linux64",
        "linux-make": "linux32",
        "win64-make": "windows2012-64",
        "win-make": "windows2012-32",
        "win64": "windows2012-64",
        "win": "windows2012-32"
      };

      // Check the platform name.
      let keep = (task.platform == (aliases[platform] || platform));

      // Additional checks.
      if (platform == "linux64-asan") {
        keep &= coll("asan");
      } else if (platform == "linux64-fips") {
        keep &= coll("fips");
      } else if (platform == "linux64-make" || platform == "linux-make" ||
                 platform == "win64-make" || platform == "win-make" ||
                 platform == "aarch64-make") {
        keep &= coll("make");
      } else if (platform == "linux64-fuzz" || platform == "linux-fuzz") {
        keep &= coll("fuzz");
      } else {
        keep &= coll("opt") || coll("debug");
      }

      return keep;
    });

    if (!found) {
      return false;
    }

    // Finally, filter by build type.
    let isDebug = coll("debug") || coll("asan") || coll("make") ||
                  coll("fuzz");
    return (isDebug && opts.builds.includes("d")) ||
           (!isDebug && opts.builds.includes("o"));
  }
}

async function getCommitComment() {
  const res = await execFile('hg', ['log', '-r', '.', '-T', '{desc}']);
  return res.stdout;
};

export async function initFilter() {
  let comment = await getCommitComment();

  // Load try_task_config.json
  // Add parameters to queue for created tasks
  let config_path = path.normalize(path.join(__dirname, '../../../../try_task_config.json'))
  if (fs.existsSync(config_path)) {
    var payload = JSON.parse(fs.readFileSync(config_path));
    if (payload['version'] == 2) {
      queue.addParameters(payload['parameters']);
    }
  }

  // Check for try syntax in changeset comment.
  let match = comment.match(/\btry:\s*(.*)\s*$/m);

  // Add try syntax filter.
  if (match) {
    let match1 = match[1];
    queue.filter(filter(parseOptions(match1)));

    if (match1.includes("--nspr-patch")) {
      queue.map(task => {
        if (!task.env) {
          task.env = {};
        }
        task.env.ALLOW_NSPR_PATCH = "1";
        return task;
      });
    }
  }
}
