// 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/ast/struct_block_decoration.h"
#include "src/resolver/resolver.h"
#include "src/resolver/resolver_test_helper.h"

#include "gmock/gmock.h"

namespace tint {
namespace resolver {
namespace {

// Helpers and typedefs
template <typename T>
using DataType = builder::DataType<T>;
template <typename T>
using vec2 = builder::vec2<T>;
template <typename T>
using vec3 = builder::vec3<T>;
template <typename T>
using vec4 = builder::vec4<T>;
template <typename T>
using mat2x2 = builder::mat2x2<T>;
template <typename T>
using mat3x3 = builder::mat3x3<T>;
template <typename T>
using mat4x4 = builder::mat4x4<T>;
template <typename T>
using alias = builder::alias<T>;
using f32 = builder::f32;
using i32 = builder::i32;
using u32 = builder::u32;

struct ResolverInferredTypeTest : public resolver::TestHelper,
                                  public testing::Test {};

struct Params {
  builder::ast_expr_func_ptr create_value;
  builder::sem_type_func_ptr create_expected_type;
};

template <typename T>
constexpr Params ParamsFor() {
  return Params{DataType<T>::Expr, DataType<T>::Sem};
}

Params all_cases[] = {
    ParamsFor<bool>(),                //
    ParamsFor<u32>(),                 //
    ParamsFor<i32>(),                 //
    ParamsFor<f32>(),                 //
    ParamsFor<vec3<bool>>(),          //
    ParamsFor<vec3<i32>>(),           //
    ParamsFor<vec3<u32>>(),           //
    ParamsFor<vec3<f32>>(),           //
    ParamsFor<mat3x3<i32>>(),         //
    ParamsFor<mat3x3<u32>>(),         //
    ParamsFor<mat3x3<f32>>(),         //
    ParamsFor<alias<bool>>(),         //
    ParamsFor<alias<u32>>(),          //
    ParamsFor<alias<i32>>(),          //
    ParamsFor<alias<f32>>(),          //
    ParamsFor<alias<vec3<bool>>>(),   //
    ParamsFor<alias<vec3<i32>>>(),    //
    ParamsFor<alias<vec3<u32>>>(),    //
    ParamsFor<alias<vec3<f32>>>(),    //
    ParamsFor<alias<mat3x3<i32>>>(),  //
    ParamsFor<alias<mat3x3<u32>>>(),  //
    ParamsFor<alias<mat3x3<f32>>>(),  //
};

using ResolverInferredTypeParamTest = ResolverTestWithParam<Params>;

TEST_P(ResolverInferredTypeParamTest, GlobalLet_Pass) {
  auto& params = GetParam();

  auto* expected_type = params.create_expected_type(*this);

  // let a = <type constructor>;
  auto* ctor_expr = params.create_value(*this, 0);
  auto* var = GlobalConst("a", nullptr, ctor_expr);
  WrapInFunction();

  EXPECT_TRUE(r()->Resolve()) << r()->error();
  EXPECT_EQ(TypeOf(var), expected_type);
}

TEST_P(ResolverInferredTypeParamTest, GlobalVar_Fail) {
  auto& params = GetParam();

  // var a = <type constructor>;
  auto* ctor_expr = params.create_value(*this, 0);
  Global(Source{{12, 34}}, "a", nullptr, ast::StorageClass::kPrivate,
         ctor_expr);
  WrapInFunction();

  EXPECT_FALSE(r()->Resolve());
  EXPECT_EQ(r()->error(),
            "12:34 error: global var declaration must specify a type");
}

TEST_P(ResolverInferredTypeParamTest, LocalLet_Pass) {
  auto& params = GetParam();

  auto* expected_type = params.create_expected_type(*this);

  // let a = <type constructor>;
  auto* ctor_expr = params.create_value(*this, 0);
  auto* var = Const("a", nullptr, ctor_expr);
  WrapInFunction(var);

  EXPECT_TRUE(r()->Resolve()) << r()->error();
  EXPECT_EQ(TypeOf(var), expected_type);
}

TEST_P(ResolverInferredTypeParamTest, LocalVar_Pass) {
  auto& params = GetParam();

  auto* expected_type = params.create_expected_type(*this);

  // var a = <type constructor>;
  auto* ctor_expr = params.create_value(*this, 0);
  auto* var = Var("a", nullptr, ast::StorageClass::kFunction, ctor_expr);
  WrapInFunction(var);

  EXPECT_TRUE(r()->Resolve()) << r()->error();
  EXPECT_EQ(TypeOf(var)->UnwrapRef(), expected_type);
}

INSTANTIATE_TEST_SUITE_P(ResolverTest,
                         ResolverInferredTypeParamTest,
                         testing::ValuesIn(all_cases));

TEST_F(ResolverInferredTypeTest, InferArray_Pass) {
  auto* type = ty.array(ty.u32(), 10);
  auto* expected_type =
      create<sem::Array>(create<sem::U32>(), 10, 4, 4 * 10, 4, true);

  auto* ctor_expr = Construct(type);
  auto* var = Var("a", nullptr, ast::StorageClass::kFunction, ctor_expr);
  WrapInFunction(var);

  EXPECT_TRUE(r()->Resolve()) << r()->error();
  EXPECT_EQ(TypeOf(var)->UnwrapRef(), expected_type);
}

TEST_F(ResolverInferredTypeTest, InferStruct_Pass) {
  auto* member = Member("x", ty.i32());
  auto* str = Structure("S", {member}, {create<ast::StructBlockDecoration>()});

  auto* expected_type =
      create<sem::Struct>(str,
                          sem::StructMemberList{create<sem::StructMember>(
                              member, create<sem::I32>(), 0, 0, 0, 4)},
                          0, 4, 4);

  auto* ctor_expr = Construct(ty.Of(str));

  auto* var = Var("a", nullptr, ast::StorageClass::kFunction, ctor_expr);
  WrapInFunction(var);

  EXPECT_TRUE(r()->Resolve()) << r()->error();
  EXPECT_EQ(TypeOf(var)->UnwrapRef(), expected_type);
}

}  // namespace
}  // namespace resolver
}  // namespace tint
