// 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_TRANSFORM_TEST_HELPER_H_
#define SRC_TRANSFORM_TEST_HELPER_H_

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

#include "gtest/gtest.h"
#include "src/reader/wgsl/parser.h"
#include "src/transform/manager.h"
#include "src/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();
    return TRANSFORM().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_TRANSFORM_TEST_HELPER_H_
