// 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 {
namespace 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 transform
}  // namespace tint

#endif  // SRC_TINT_TRANSFORM_TEST_HELPER_H_
