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

#include "src/transform/transform.h"
#include "src/clone_context.h"
#include "src/program_builder.h"

#include "gtest/gtest.h"

namespace tint {
namespace transform {
namespace {

// Inherit from Transform so we have access to protected methods
struct CreateASTTypeForTest : public testing::Test, public Transform {
  Output Run(const Program*, const DataMap&) override { return {}; }

  ast::Type* create(
      std::function<sem::Type*(ProgramBuilder&)> create_sem_type) {
    ProgramBuilder sem_type_builder;
    auto* sem_type = create_sem_type(sem_type_builder);
    Program program(std::move(sem_type_builder));
    CloneContext ctx(&ast_type_builder, &program, false);
    return CreateASTTypeFor(&ctx, sem_type);
  }

  ProgramBuilder ast_type_builder;
};

TEST_F(CreateASTTypeForTest, Basic) {
  EXPECT_TRUE(create([](ProgramBuilder& b) {
                return b.create<sem::I32>();
              })->Is<ast::I32>());
  EXPECT_TRUE(create([](ProgramBuilder& b) {
                return b.create<sem::U32>();
              })->Is<ast::U32>());
  EXPECT_TRUE(create([](ProgramBuilder& b) {
                return b.create<sem::F32>();
              })->Is<ast::F32>());
  EXPECT_TRUE(create([](ProgramBuilder& b) {
                return b.create<sem::Bool>();
              })->Is<ast::Bool>());
  EXPECT_TRUE(create([](ProgramBuilder& b) {
                return b.create<sem::Void>();
              })->Is<ast::Void>());
}

TEST_F(CreateASTTypeForTest, Matrix) {
  auto* mat = create([](ProgramBuilder& b) {
    auto* column_type = b.create<sem::Vector>(b.create<sem::F32>(), 2u);
    return b.create<sem::Matrix>(column_type, 3u);
  });
  ASSERT_TRUE(mat->Is<ast::Matrix>());
  ASSERT_TRUE(mat->As<ast::Matrix>()->type()->Is<ast::F32>());
  ASSERT_EQ(mat->As<ast::Matrix>()->columns(), 3u);
  ASSERT_EQ(mat->As<ast::Matrix>()->rows(), 2u);
}

TEST_F(CreateASTTypeForTest, Vector) {
  auto* vec = create([](ProgramBuilder& b) {
    return b.create<sem::Vector>(b.create<sem::F32>(), 2);
  });
  ASSERT_TRUE(vec->Is<ast::Vector>());
  ASSERT_TRUE(vec->As<ast::Vector>()->type()->Is<ast::F32>());
  ASSERT_EQ(vec->As<ast::Vector>()->size(), 2u);
}

TEST_F(CreateASTTypeForTest, Array) {
  auto* arr = create([](ProgramBuilder& b) {
    return b.create<sem::ArrayType>(b.create<sem::F32>(), 4,
                                    ast::DecorationList{
                                        b.create<ast::StrideDecoration>(32u),
                                    });
  });
  ASSERT_TRUE(arr->Is<ast::Array>());
  ASSERT_TRUE(arr->As<ast::Array>()->type()->Is<ast::F32>());
  ASSERT_EQ(arr->As<ast::Array>()->size(), 4u);
  ASSERT_EQ(arr->As<ast::Array>()->decorations().size(), 1u);
  ASSERT_TRUE(
      arr->As<ast::Array>()->decorations()[0]->Is<ast::StrideDecoration>());
  ASSERT_EQ(arr->As<ast::Array>()
                ->decorations()[0]
                ->As<ast::StrideDecoration>()
                ->stride(),
            32u);
}

TEST_F(CreateASTTypeForTest, AccessControl) {
  auto* ac = create([](ProgramBuilder& b) {
    auto str = b.Structure("S", {}, {});
    return b.create<sem::AccessControl>(ast::AccessControl::kReadOnly, str);
  });
  ASSERT_TRUE(ac->Is<ast::AccessControl>());
  EXPECT_EQ(ac->As<ast::AccessControl>()->access_control(),
            ast::AccessControl::kReadOnly);
  EXPECT_TRUE(ac->As<ast::AccessControl>()->type()->Is<ast::TypeName>());
}

TEST_F(CreateASTTypeForTest, Struct) {
  auto* str = create([](ProgramBuilder& b) {
    auto* impl = b.Structure("S", {}, {}).ast;
    return b.create<sem::StructType>(const_cast<ast::Struct*>(impl));
  });
  ASSERT_TRUE(str->Is<ast::TypeName>());
  EXPECT_EQ(
      ast_type_builder.Symbols().NameFor(str->As<ast::TypeName>()->name()),
      "S");
}

}  // namespace
}  // namespace transform
}  // namespace tint
