/*
 * Copyright 2021 WebAssembly Community Group participants
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <optional>
#include <random>
#include <string>

#include "support/command-line.h"
#include "tools/fuzzing/heap-types.h"
#include "tools/fuzzing/random.h"

namespace wasm {

using RandEngine = std::mt19937_64;

uint64_t getSeed() {
  // Return a (truly) random 64-bit value.
  std::random_device rand;
  return std::uniform_int_distribution<uint64_t>{}(rand);
}

struct Fuzzer {
  bool verbose;

  void run(uint64_t seed) {
    // TODO: Reset the global type state to avoid monotonically increasing
    // memory use.
    RandEngine getRand(seed);
    std::cout << "Running with seed " << seed << "\n";

    // 4kb of random bytes should be enough for anyone!
    std::vector<char> bytes(4096);
    for (size_t i = 0; i < bytes.size(); i += sizeof(uint64_t)) {
      *(uint64_t*)(bytes.data() + i) = getRand();
    }
    Random rand(std::move(bytes));

    // TODO: Options to control the size or set it randomly.
    HeapTypeGenerator generator =
      HeapTypeGenerator::create(rand, FeatureSet::All, 20);
    auto result = generator.builder.build();
    if (auto* err = result.getError()) {
      Fatal() << "Failed to build types: " << err->reason << " at index "
              << err->index;
    }
    auto types = *result;

    if (verbose) {
      printTypes(types);
    }

    checkSubtypes(types, generator.subtypeIndices);
    checkLUBs(types);
  }

  void printTypes(const std::vector<HeapType>& types) {
    std::cout << "Built " << types.size() << " types:\n";
    // Record indices to use as names.
    std::unordered_map<HeapType, size_t> typeIndices;
    for (size_t i = 0; i < types.size(); ++i) {
      typeIndices.insert({types[i], i});
    }
    for (size_t i = 0; i < types.size(); ++i) {
      auto type = types[i];
      std::cout << "(type $" << i << ' ';
      if (auto prev = typeIndices[type]; !type.isBasic() && prev != i) {
        std::cout << "identical to $" << prev;
      } else {
        std::cout << type.print([&](HeapType t) -> TypeNames {
          if (auto it = typeIndices.find(t); it != typeIndices.end()) {
            return {std::to_string(it->second), {}};
          } else {
            Fatal() << "trying to print unknown heap type";
          }
        });
      }
      std::cout << ")\n";
    }
  }

  void checkSubtypes(const std::vector<HeapType>& types,
                     const std::vector<std::vector<Index>>& subtypeIndices) {
    for (size_t super = 0; super < types.size(); ++super) {
      for (auto sub : subtypeIndices[super]) {
        if (!HeapType::isSubType(types[sub], types[super])) {
          Fatal() << "HeapType " << sub << " should be a subtype of HeapType "
                  << super << " but is not!\n"
                  << sub << ": " << types[sub] << "\n"
                  << super << ": " << types[super] << "\n";
        }
      }
    }
  }

  void checkLUBs(const std::vector<HeapType>& types) {
    // For each unordered pair of types...
    for (size_t i = 0; i < types.size(); ++i) {
      for (size_t j = i; j < types.size(); ++j) {
        HeapType a = types[i], b = types[j];
        // Check that their LUB is stable when calculated multiple times and in
        // reverse order.
        HeapType lub = HeapType::getLeastUpperBound(a, b);
        if (lub != HeapType::getLeastUpperBound(b, a) ||
            lub != HeapType::getLeastUpperBound(a, b)) {
          Fatal() << "Could not calculate a stable LUB of HeapTypes " << i
                  << " and " << j << "!\n"
                  << i << ": " << a << "\n"
                  << j << ": " << b << "\n";
        }
        // Check that each type is a subtype of the LUB.
        if (!HeapType::isSubType(a, lub)) {
          Fatal() << "HeapType " << i
                  << " is not a subtype of its LUB with HeapType " << j << "!\n"
                  << i << ": " << a << "\n"
                  << j << ": " << b << "\n"
                  << "lub: " << lub << "\n";
        }
        if (!HeapType::isSubType(b, lub)) {
          Fatal() << "HeapType " << j
                  << " is not a subtype of its LUB with HeapType " << i << "!\n"
                  << i << ": " << a << "\n"
                  << j << ": " << b << "\n"
                  << "lub: " << lub << "\n";
        }
        // Check that the LUB of each type and the original LUB is still the
        // original LUB.
        if (lub != HeapType::getLeastUpperBound(a, lub)) {
          Fatal() << "The LUB of HeapType " << i << " and HeapType " << j
                  << " should be the LUB of itself and HeapType " << i
                  << ", but it is not!\n"
                  << i << ": " << a << "\n"
                  << j << ": " << b << "\n"
                  << "lub: " << lub << "\n";
        }
        if (lub != HeapType::getLeastUpperBound(lub, b)) {
          Fatal() << "The LUB of HeapType " << i << " and HeapType " << j
                  << " should be the LUB of itself and HeapType " << j
                  << ", but it is not!\n"
                  << i << ": " << a << "\n"
                  << j << ": " << b << "\n"
                  << "lub: " << lub << "\n";
        }
      }
    }
  }
};

} // namespace wasm

int main(int argc, const char* argv[]) {
  using namespace wasm;

  const std::string WasmFuzzTypesOption = "wasm-fuzz-types options";

  Options options("wasm-fuzz-types",
                  "Fuzz type construction, canonicalization, and operations");

  std::optional<uint64_t> seed;
  options.add("--seed",
              "",
              "Run a single workload generated by the given seed",
              WasmFuzzTypesOption,
              Options::Arguments::One,
              [&](Options*, const std::string& arg) {
                seed = uint64_t(std::stoull(arg));
              });

  bool verbose = false;
  options.add("--verbose",
              "-v",
              "Print extra information",
              WasmFuzzTypesOption,
              Options::Arguments::Zero,
              [&](Options*, const std::string& arg) { verbose = true; });

  TypeSystem system = TypeSystem::Nominal;
  options.add(
    "--nominal",
    "",
    "Use the nominal type system (default)",
    WasmFuzzTypesOption,
    Options::Arguments::Zero,
    [&](Options*, const std::string& arg) { system = TypeSystem::Nominal; });
  options.add("--structural",
              "",
              "Use the equirecursive type system",
              WasmFuzzTypesOption,
              Options::Arguments::Zero,
              [&](Options*, const std::string& arg) {
                system = TypeSystem::Equirecursive;
              });
  options.add("--hybrid",
              "",
              "Use the isorecursive hybrid type system",
              WasmFuzzTypesOption,
              Options::Arguments::Zero,
              [&](Options*, const std::string& arg) {
                system = TypeSystem::Isorecursive;
              });

  options.parse(argc, argv);

  setTypeSystem(system);

  Fuzzer fuzzer{verbose};
  if (seed) {
    // Run just a single workload with the given seed.
    fuzzer.run(*seed);
  } else {
    // Continuously run workloads with new randomly generated seeds.
    size_t i = 0;
    RandEngine nextSeed(getSeed());
    while (true) {
      std::cout << "Iteration " << ++i << "\n";
      fuzzer.run(nextSeed());
    }
  }
  return 0;
}
