// Copyright 2020 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/writer/pack_coord_arrayidx.h"

#include <utility>

#include "src/ast/expression.h"
#include "src/ast/type/vector_type.h"
#include "src/ast/type_constructor_expression.h"

namespace tint {
namespace writer {

namespace {

ast::TypeConstructorExpression* AsVectorConstructor(ast::Expression* expr) {
  if (!expr->IsConstructor())
    return nullptr;
  auto* constructor = expr->AsConstructor();
  if (!constructor->IsTypeConstructor()) {
    return nullptr;
  }
  auto* type_constructor = constructor->AsTypeConstructor();
  if (!type_constructor->type()->IsVector()) {
    return nullptr;
  }
  return type_constructor;
}

}  // namespace

bool PackCoordAndArrayIndex(
    ast::Expression* coords,
    ast::Expression* array_idx,
    std::function<bool(ast::TypeConstructorExpression*)> callback) {
  uint32_t packed_size;
  ast::type::Type* packed_el_ty;  // Currenly must be f32.
  if (coords->result_type()->IsVector()) {
    auto* vec = coords->result_type()->AsVector();
    packed_size = vec->size() + 1;
    packed_el_ty = vec->type();
  } else {
    packed_size = 2;
    packed_el_ty = coords->result_type();
  }

  if (!packed_el_ty) {
    return false;  // missing type info
  }

  // Cast array_idx to the vector element type
  ast::TypeConstructorExpression array_index_cast(packed_el_ty, {array_idx});
  array_index_cast.set_result_type(packed_el_ty);

  ast::type::VectorType packed_ty(packed_el_ty, packed_size);

  // If the coordinates are already passed in a vector constructor, extract
  // the elements into the new vector instead of nesting a vector-in-vector.
  ast::ExpressionList packed;
  if (auto* vc = AsVectorConstructor(coords)) {
    packed = vc->values();
  } else {
    packed.emplace_back(coords);
  }
  packed.emplace_back(&array_index_cast);

  ast::TypeConstructorExpression constructor{&packed_ty, std::move(packed)};

  return callback(&constructor);
}

}  // namespace writer
}  // namespace tint
