// 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/type/array_type.h"

#include <cmath>
#include <memory>

#include "src/ast/module.h"
#include "src/ast/stride_decoration.h"
#include "src/clone_context.h"
#include "src/type/vector_type.h"

TINT_INSTANTIATE_CLASS_ID(tint::type::Array);

namespace tint {
namespace type {

Array::Array(Type* subtype, uint32_t size, ast::ArrayDecorationList decorations)
    : subtype_(subtype), size_(size), decos_(decorations) {}

Array::Array(Array&&) = default;

Array::~Array() = default;

uint64_t Array::MinBufferBindingSize(MemoryLayout mem_layout) const {
  if (!has_array_stride()) {
    // Arrays in buffers are required to have a stride.
    return 0;
  }

  if (IsRuntimeArray()) {
    // WebGPU spec 10.1.2:
    // If the last field of the corresponding structure defined in the shader
    // has an unbounded array type, then the value of minBufferBindingSize must
    // be greater than or equal to the byte offset of that field plus the stride
    // of the unbounded array
    return array_stride();
  } else {
    // Not including the padding for the last element
    return (size_ - 1) * array_stride() +
           subtype_->MinBufferBindingSize(mem_layout);
  }
}

uint64_t Array::BaseAlignment(MemoryLayout mem_layout) const {
  if (mem_layout == MemoryLayout::kUniformBuffer) {
    float aligment = 16;  // for a vec4
    float unaligned = static_cast<float>(subtype_->BaseAlignment(mem_layout));
    return static_cast<uint64_t>(aligment * std::ceil(unaligned / aligment));
  } else if (mem_layout == MemoryLayout::kStorageBuffer) {
    return subtype_->BaseAlignment(mem_layout);
  }
  return 0;
}

uint32_t Array::array_stride() const {
  for (auto* deco : decos_) {
    if (auto* stride = deco->As<ast::StrideDecoration>()) {
      return stride->stride();
    }
  }
  return 0;
}

bool Array::has_array_stride() const {
  for (auto* deco : decos_) {
    if (deco->Is<ast::StrideDecoration>()) {
      return true;
    }
  }
  return false;
}

std::string Array::type_name() const {
  assert(subtype_);

  std::string type_name = "__array" + subtype_->type_name();
  if (!IsRuntimeArray())
    type_name += "_" + std::to_string(size_);
  if (has_array_stride())
    type_name += "_stride_" + std::to_string(array_stride());

  return type_name;
}

Array* Array::Clone(CloneContext* ctx) const {
  return ctx->mod->create<Array>(ctx->Clone(subtype_), size_,
                                 ctx->Clone(decorations()));
}

}  // namespace type
}  // namespace tint
