// 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_
