// Copyright 2021 The Tint Authors.
//
// 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.

#ifndef FUZZERS_DATA_BUILDER_H_
#define FUZZERS_DATA_BUILDER_H_

#include <cassert>
#include <functional>
#include <string>
#include <unordered_map>
#include <vector>

#include "fuzzers/random_generator.h"
#include "src/writer/hlsl/generator.h"
#include "src/writer/msl/generator.h"

namespace tint {
namespace fuzzers {

/// Builder for generic pseudo-random data
class DataBuilder {
 public:
  /// @brief Initializes the internal engine using a seed value
  /// @param seed - seed value passed to engine
  explicit DataBuilder(uint64_t seed) : generator_(seed) {}

  /// @brief Initializes the internal engine using seed data
  /// @param data - data fuzzer to calculate seed from
  /// @param size - size of data buffer
  explicit DataBuilder(const uint8_t* data, size_t size)
      : generator_(RandomGenerator::CalculateSeed(data, size)) {
    assert(data != nullptr && "|data| must be !nullptr");
  }

  ~DataBuilder() = default;
  DataBuilder(DataBuilder&&) = default;

  /// Generate pseudo-random data of a specific type
  /// @tparam T - type of data to produce
  /// @returns pseudo-random data of type T
  template <typename T>
  T build() {
    return BuildImpl<T>::impl(this);
  }

  /// Generate pseudo-random data of a specific type in a vector
  /// @tparam T - data type held vector
  /// @returns pseudo-random data of type std::vector<T>
  template <typename T>
  std::vector<T> vector() {
    auto count = build<uint8_t>();
    std::vector<T> out(count);
    for (uint8_t i = 0; i < count; i++) {
      out[i] = build<T>();
    }
    return out;
  }

  /// Generate complex pseudo-random data of a specific type in a vector
  /// @tparam T - data type held vector
  /// @tparam Callback - callback that takes in a DataBuilder* and returns a T
  /// @param generate - callback for generating each instance of T
  /// @returns pseudo-random data of type std::vector<T>
  template <typename T, typename Callback>
  std::vector<T> vector(Callback generate) {
    auto count = build<uint8_t>();
    std::vector<T> out(count);
    for (size_t i = 0; i < count; i++) {
      out[i] = generate(this);
    }
    return out;
  }

  /// Generate an pseudo-random entry to a enum class.
  /// Assumes enum is tightly packed starting at 0.
  /// @tparam T - type of enum class
  /// @param count - number of entries in enum class
  /// @returns a random enum class entry
  template <typename T>
  T enum_class(uint32_t count) {
    return static_cast<T>(generator_.Get4Bytes() % count);
  }

 private:
  RandomGenerator generator_;

  // Disallow copy & assign
  DataBuilder(const DataBuilder&) = delete;
  DataBuilder& operator=(const DataBuilder&) = delete;

  /// Get N bytes of pseudo-random data
  /// @param out - pointer to location to save data
  /// @param n - number of bytes to get
  void build(void* out, size_t n) {
    assert(out != nullptr && "|out| cannot be nullptr");
    assert(n > 0 && "|n| must be > 0");

    generator_.GetNBytes(reinterpret_cast<uint8_t*>(out), n);
  }

  /// Generate pseudo-random data of a specific type into an output var
  /// @tparam T - type of data to produce
  /// @param out - output var to generate into
  template <typename T>
  void build(T& out) {
    out = build<T>();
  }

  /// Implementation of ::build<T>()
  /// @tparam T - type of data to produce
  template <typename T>
  struct BuildImpl {
    /// Generate a pseudo-random variable of type T
    /// @param b - data builder to use
    /// @returns a variable of type T filled with pseudo-random data
    static T impl(DataBuilder* b) {
      T out{};
      b->build(&out, sizeof(T));
      return out;
    }
  };

  /// Specialization for std::string
  template <>
  struct BuildImpl<std::string> {
    /// Generate a pseudo-random string
    /// @param b - data builder to use
    /// @returns a string filled with pseudo-random data
    static std::string impl(DataBuilder* b) {
      auto count = b->build<uint8_t>();
      if (count == 0) {
        return "";
      }
      std::vector<uint8_t> source(count);
      b->build(source.data(), count);
      return {source.begin(), source.end()};
    }
  };

  /// Specialization for bool
  template <>
  struct BuildImpl<bool> {
    /// Generate a pseudo-random bool
    /// @param b - data builder to use
    /// @returns a boolean with even odds of being true or false
    static bool impl(DataBuilder* b) { return b->generator_.GetBool(); }
  };

  /// Specialization for writer::msl::Options
  template <>
  struct BuildImpl<writer::msl::Options> {
    /// Generate a pseudo-random writer::msl::Options struct
    /// @param b - data builder to use
    /// @returns writer::msl::Options filled with pseudo-random data
    static writer::msl::Options impl(DataBuilder* b) {
      writer::msl::Options out{};
      b->build(out.buffer_size_ubo_index);
      b->build(out.fixed_sample_mask);
      b->build(out.emit_vertex_point_size);
      b->build(out.disable_workgroup_init);
      b->build(out.array_length_from_uniform);
      return out;
    }
  };

  /// Specialization for writer::hlsl::Options
  template <>
  struct BuildImpl<writer::hlsl::Options> {
    /// Generate a pseudo-random writer::hlsl::Options struct
    /// @param b - data builder to use
    /// @returns writer::hlsl::Options filled with pseudo-random data
    static writer::hlsl::Options impl(DataBuilder* b) {
      writer::hlsl::Options out{};
      b->build(out.root_constant_binding_point);
      b->build(out.disable_workgroup_init);
      b->build(out.array_length_from_uniform);
      return out;
    }
  };

  /// Specialization for writer::spirv::Options
  template <>
  struct BuildImpl<writer::spirv::Options> {
    /// Generate a pseudo-random writer::spirv::Options struct
    /// @param b - data builder to use
    /// @returns writer::spirv::Options filled with pseudo-random data
    static writer::spirv::Options impl(DataBuilder* b) {
      writer::spirv::Options out{};
      b->build(out.emit_vertex_point_size);
      b->build(out.disable_workgroup_init);
      return out;
    }
  };

  /// Specialization for writer::ArrayLengthFromUniformOptions
  template <>
  struct BuildImpl<writer::ArrayLengthFromUniformOptions> {
    /// Generate a pseudo-random writer::ArrayLengthFromUniformOptions struct
    /// @param b - data builder to use
    /// @returns writer::ArrayLengthFromUniformOptions filled with pseudo-random
    /// data
    static writer::ArrayLengthFromUniformOptions impl(DataBuilder* b) {
      writer::ArrayLengthFromUniformOptions out{};
      b->build(out.ubo_binding);
      b->build(out.bindpoint_to_size_index);
      return out;
    }
  };

  /// Specialization for std::unordered_map<K, V>
  template <typename K, typename V>
  struct BuildImpl<std::unordered_map<K, V>> {
    /// Generate a pseudo-random std::unordered_map<K, V>
    /// @param b - data builder to use
    /// @returns std::unordered_map<K, V> filled with
    /// pseudo-random data
    static std::unordered_map<K, V> impl(DataBuilder* b) {
      std::unordered_map<K, V> out;
      uint8_t count = b->build<uint8_t>();
      for (uint8_t i = 0; i < count; ++i) {
        out.emplace(b->build<K>(), b->build<V>());
      }
      return out;
    }
  };
};

}  // namespace fuzzers
}  // namespace tint

#endif  // FUZZERS_DATA_BUILDER_H_
