// 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 SRC_TINT_TRANSFORM_TEST_HELPER_H_
#define SRC_TINT_TRANSFORM_TEST_HELPER_H_

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

#include "gtest/gtest.h"
#include "src/tint/reader/wgsl/parser.h"
#include "src/tint/transform/manager.h"
#include "src/tint/writer/wgsl/generator.h"

namespace tint::transform {

/// @param program the program to get an output WGSL string from
/// @returns the output program as a WGSL string, or an error string if the
/// program is not valid.
inline std::string str(const Program& program) {
  diag::Formatter::Style style;
  style.print_newline_at_end = false;

  if (!program.IsValid()) {
    return diag::Formatter(style).format(program.Diagnostics());
  }

  writer::wgsl::Options options;
  auto result = writer::wgsl::Generate(&program, options);
  if (!result.success) {
    return "WGSL writer failed:\n" + result.error;
  }

  auto res = result.wgsl;
  if (res.empty()) {
    return res;
  }
  // The WGSL sometimes has two trailing newlines. Strip them
  while (res.back() == '\n') {
    res.pop_back();
  }
  if (res.empty()) {
    return res;
  }
  return "\n" + res + "\n";
}

/// Helper class for testing transforms
template <typename BASE>
class TransformTestBase : public BASE {
 public:
  /// Transforms and returns the WGSL source `in`, transformed using
  /// `transform`.
  /// @param transform the transform to apply
  /// @param in the input WGSL source
  /// @param data the optional DataMap to pass to Transform::Run()
  /// @return the transformed output
  Output Run(std::string in,
             std::unique_ptr<transform::Transform> transform,
             const DataMap& data = {}) {
    std::vector<std::unique_ptr<transform::Transform>> transforms;
    transforms.emplace_back(std::move(transform));
    return Run(std::move(in), std::move(transforms), data);
  }

  /// Transforms and returns the WGSL source `in`, transformed using
  /// a transform of type `TRANSFORM`.
  /// @param in the input WGSL source
  /// @param data the optional DataMap to pass to Transform::Run()
  /// @return the transformed output
  template <typename... TRANSFORMS>
  Output Run(std::string in, const DataMap& data = {}) {
    auto file = std::make_unique<Source::File>("test", in);
    auto program = reader::wgsl::Parse(file.get());

    // Keep this pointer alive after Transform() returns
    files_.emplace_back(std::move(file));

    return Run<TRANSFORMS...>(std::move(program), data);
  }

  /// Transforms and returns program `program`, transformed using a transform of
  /// type `TRANSFORM`.
  /// @param program the input Program
  /// @param data the optional DataMap to pass to Transform::Run()
  /// @return the transformed output
  template <typename... TRANSFORMS>
  Output Run(Program&& program, const DataMap& data = {}) {
    if (!program.IsValid()) {
      return Output(std::move(program));
    }

    Manager manager;
    for (auto* transform_ptr :
         std::initializer_list<Transform*>{new TRANSFORMS()...}) {
      manager.append(std::unique_ptr<Transform>(transform_ptr));
    }
    return manager.Run(&program, data);
  }

  /// @param program the input program
  /// @param data the optional DataMap to pass to Transform::Run()
  /// @return true if the transform should be run for the given input.
  template <typename TRANSFORM>
  bool ShouldRun(Program&& program, const DataMap& data = {}) {
    EXPECT_TRUE(program.IsValid()) << program.Diagnostics().str();
    const Transform& t = TRANSFORM();
    return t.ShouldRun(&program, data);
  }

  /// @param in the input WGSL source
  /// @param data the optional DataMap to pass to Transform::Run()
  /// @return true if the transform should be run for the given input.
  template <typename TRANSFORM>
  bool ShouldRun(std::string in, const DataMap& data = {}) {
    auto file = std::make_unique<Source::File>("test", in);
    auto program = reader::wgsl::Parse(file.get());
    return ShouldRun<TRANSFORM>(std::move(program), data);
  }

  /// @param output the output of the transform
  /// @returns the output program as a WGSL string, or an error string if the
  /// program is not valid.
  std::string str(const Output& output) {
    return transform::str(output.program);
  }

 private:
  std::vector<std::unique_ptr<Source::File>> files_;
};

using TransformTest = TransformTestBase<testing::Test>;

template <typename T>
using TransformTestWithParam = TransformTestBase<testing::TestWithParam<T>>;

}  // namespace tint::transform

#endif  // SRC_TINT_TRANSFORM_TEST_HELPER_H_
