// Copyright 2020 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 SRC_TINT_WRITER_SPIRV_TEST_HELPER_H_
#define SRC_TINT_WRITER_SPIRV_TEST_HELPER_H_

#include <memory>
#include <string>
#include <utility>

#include "gtest/gtest.h"
#include "spirv-tools/libspirv.hpp"
#include "src/tint/writer/spirv/binary_writer.h"

namespace tint::writer::spirv {

/// Helper class for testing
template <typename BASE>
class TestHelperBase : public ProgramBuilder, public BASE {
 public:
  TestHelperBase() = default;
  ~TestHelperBase() override = default;

  /// Builds and returns a spirv::Builder from the program.
  /// @note The spirv::Builder is only built once. Multiple calls to Build()
  /// will return the same spirv::Builder without rebuilding.
  /// @return the built spirv::Builder
  spirv::Builder& Build() {
    if (spirv_builder) {
      return *spirv_builder;
    }
    [&]() {
      ASSERT_TRUE(IsValid()) << "Builder program is not valid\n"
                             << diag::Formatter().format(Diagnostics());
    }();
    program = std::make_unique<Program>(std::move(*this));
    [&]() {
      ASSERT_TRUE(program->IsValid())
          << diag::Formatter().format(program->Diagnostics());
    }();
    spirv_builder = std::make_unique<spirv::Builder>(program.get());
    return *spirv_builder;
  }

  /// Builds the program, runs the program through the transform::Spirv
  /// sanitizer and returns a spirv::Builder from the sanitized program.
  /// @param options The SPIR-V generator options.
  /// @note The spirv::Builder is only built once. Multiple calls to Build()
  /// will return the same spirv::Builder without rebuilding.
  /// @return the built spirv::Builder
  spirv::Builder& SanitizeAndBuild(const Options& options = {}) {
    if (spirv_builder) {
      return *spirv_builder;
    }
    [&]() {
      ASSERT_TRUE(IsValid()) << "Builder program is not valid\n"
                             << diag::Formatter().format(Diagnostics());
    }();
    program = std::make_unique<Program>(std::move(*this));
    [&]() {
      ASSERT_TRUE(program->IsValid())
          << diag::Formatter().format(program->Diagnostics());
    }();
    auto result = Sanitize(program.get(), options);
    [&]() {
      ASSERT_TRUE(result.program.IsValid())
          << diag::Formatter().format(result.program.Diagnostics());
    }();
    *program = std::move(result.program);
    spirv_builder = std::make_unique<spirv::Builder>(program.get());
    return *spirv_builder;
  }

  /// Validate passes the generated SPIR-V of the builder `b` to the SPIR-V
  /// Tools Validator. If the validator finds problems the test will fail.
  /// @param b the spirv::Builder containing the built SPIR-V module
  void Validate(spirv::Builder& b) {
    BinaryWriter writer;
    writer.WriteHeader(b.id_bound());
    writer.WriteBuilder(&b);
    auto binary = writer.result();

    std::string spv_errors;
    auto msg_consumer = [&spv_errors](spv_message_level_t level, const char*,
                                      const spv_position_t& position,
                                      const char* message) {
      switch (level) {
        case SPV_MSG_FATAL:
        case SPV_MSG_INTERNAL_ERROR:
        case SPV_MSG_ERROR:
          spv_errors += "error: line " + std::to_string(position.index) + ": " +
                        message + "\n";
          break;
        case SPV_MSG_WARNING:
          spv_errors += "warning: line " + std::to_string(position.index) +
                        ": " + message + "\n";
          break;
        case SPV_MSG_INFO:
          spv_errors += "info: line " + std::to_string(position.index) + ": " +
                        message + "\n";
          break;
        case SPV_MSG_DEBUG:
          break;
      }
    };

    spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_2);
    tools.SetMessageConsumer(msg_consumer);
    ASSERT_TRUE(tools.Validate(binary)) << spv_errors;
  }

  /// The program built with a call to Build()
  std::unique_ptr<Program> program;

 private:
  std::unique_ptr<spirv::Builder> spirv_builder;
};
using TestHelper = TestHelperBase<testing::Test>;

template <typename T>
using TestParamHelper = TestHelperBase<testing::TestWithParam<T>>;

}  // namespace tint::writer::spirv

#endif  // SRC_TINT_WRITER_SPIRV_TEST_HELPER_H_
