// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "impeller/scene/skin.h"

#include <cmath>
#include <memory>
#include <optional>
#include <vector>

#include "flutter/fml/logging.h"
#include "impeller/renderer/allocator.h"
#include "impeller/scene/importer/conversions.h"

namespace impeller {
namespace scene {

std::unique_ptr<Skin> Skin::MakeFromFlatbuffer(
    const fb::Skin& skin,
    const std::vector<std::shared_ptr<Node>>& scene_nodes) {
  if (!skin.joints() || !skin.inverse_bind_matrices() ||
      skin.joints()->size() != skin.inverse_bind_matrices()->size()) {
    VALIDATION_LOG << "Skin data is missing joints or bind matrices.";
    return nullptr;
  }

  Skin result;

  result.joints_.reserve(skin.joints()->size());
  for (auto joint : *skin.joints()) {
    if (joint < 0 || static_cast<size_t>(joint) > scene_nodes.size()) {
      VALIDATION_LOG << "Skin joint index out of range.";
      result.joints_.push_back(nullptr);
      continue;
    }
    if (scene_nodes[joint]) {
      scene_nodes[joint]->SetIsJoint(true);
    }
    result.joints_.push_back(scene_nodes[joint]);
  }

  result.inverse_bind_matrices_.reserve(skin.inverse_bind_matrices()->size());
  for (auto matrix : *skin.inverse_bind_matrices()) {
    if (!matrix) {
      result.inverse_bind_matrices_.push_back(Matrix());
      continue;
    }
    result.inverse_bind_matrices_.push_back(importer::ToMatrix(*matrix));
  }

  return std::make_unique<Skin>(std::move(result));
}

Skin::Skin() = default;

Skin::~Skin() = default;

Skin::Skin(Skin&&) = default;

Skin& Skin::operator=(Skin&&) = default;

std::shared_ptr<Texture> Skin::GetJointsTexture(Allocator& allocator) {
  // Each joint has a matrix. 1 matrix = 16 floats. 1 pixel = 4 floats.
  // Therefore, each joint needs 4 pixels.
  auto required_pixels = joints_.size() * 4;
  auto dimension_size = std::max(
      2u,
      Allocation::NextPowerOfTwoSize(std::ceil(std::sqrt(required_pixels))));

  impeller::TextureDescriptor texture_descriptor;
  texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
  texture_descriptor.format = PixelFormat::kR32G32B32A32Float;
  texture_descriptor.size = {dimension_size, dimension_size};
  texture_descriptor.mip_count = 1u;

  auto result = allocator.CreateTexture(texture_descriptor);
  result->SetLabel("Joints Texture");
  if (!result) {
    FML_LOG(ERROR) << "Could not create joint texture.";
    return nullptr;
  }

  std::vector<Matrix> joints;
  joints.resize(result->GetSize().Area() / 4, Matrix());
  FML_DCHECK(joints.size() >= joints_.size());
  for (size_t joint_i = 0; joint_i < joints_.size(); joint_i++) {
    const Node* joint = joints_[joint_i].get();
    if (!joint) {
      // When a joint is missing, just let it remain as an identity matrix.
      continue;
    }

    // Compute a model space matrix for the joint by walking up the bones to the
    // skeleton root.
    while (joint && joint->IsJoint()) {
      joints[joint_i] = joint->GetLocalTransform() * joints[joint_i];
      joint = joint->GetParent();
    }

    // Get the joint transform relative to the default pose of the bone by
    // incorporating the joint's inverse bind matrix. The inverse bind matrix
    // transforms from model space to the default pose space of the joint. The
    // result is a model space matrix that only captures the difference between
    // the joint's default pose and the joint's current pose in the scene. This
    // is necessary because the skinned model's vertex positions (which _define_
    // the default pose) are all in model space.
    joints[joint_i] = joints[joint_i] * inverse_bind_matrices_[joint_i];
  }

  if (!result->SetContents(reinterpret_cast<uint8_t*>(joints.data()),
                           joints.size() * sizeof(Matrix))) {
    FML_LOG(ERROR) << "Could not set contents of joint texture.";
    return nullptr;
  }

  return result;
}

}  // namespace scene
}  // namespace impeller
