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

#include <inttypes.h>
#include <atomic>
#include <memory>
#include <vector>

#include "flutter/fml/logging.h"
#include "impeller/base/strings.h"
#include "impeller/base/thread.h"
#include "impeller/base/validation.h"
#include "impeller/geometry/matrix.h"
#include "impeller/image/decompressed_image.h"
#include "impeller/scene/animation/animation_player.h"
#include "impeller/scene/importer/conversions.h"
#include "impeller/scene/importer/scene_flatbuffers.h"
#include "impeller/scene/mesh.h"
#include "impeller/scene/node.h"
#include "impeller/scene/scene_encoder.h"

namespace impeller {
namespace scene {

static std::atomic_uint64_t kNextNodeID = 0;

void Node::MutationLog::Append(const Entry& entry) {
  WriterLock lock(write_mutex_);
  dirty_ = true;
  entries_.push_back(entry);
}

std::optional<std::vector<Node::MutationLog::Entry>>
Node::MutationLog::Flush() {
  WriterLock lock(write_mutex_);
  if (!dirty_) {
    return std::nullopt;
  }
  dirty_ = false;
  auto result = entries_;
  entries_ = {};
  return result;
}

std::shared_ptr<Node> Node::MakeFromFlatbuffer(
    const fml::Mapping& ipscene_mapping,
    Allocator& allocator) {
  flatbuffers::Verifier verifier(ipscene_mapping.GetMapping(),
                                 ipscene_mapping.GetSize());
  if (!fb::VerifySceneBuffer(verifier)) {
    VALIDATION_LOG << "Failed to unpack scene: Scene flatbuffer is invalid.";
    return nullptr;
  }

  return Node::MakeFromFlatbuffer(*fb::GetScene(ipscene_mapping.GetMapping()),
                                  allocator);
}

static std::shared_ptr<Texture> UnpackTextureFromFlatbuffer(
    const fb::Texture* iptexture,
    Allocator& allocator) {
  if (iptexture == nullptr || iptexture->embedded_image() == nullptr ||
      iptexture->embedded_image()->bytes() == nullptr) {
    return nullptr;
  }

  auto embedded = iptexture->embedded_image();

  uint8_t bytes_per_component = 0;
  switch (embedded->component_type()) {
    case fb::ComponentType::k8Bit:
      bytes_per_component = 1;
      break;
    case fb::ComponentType::k16Bit:
      // bytes_per_component = 2;
      FML_LOG(WARNING) << "16 bit textures not yet supported.";
      return nullptr;
  }

  DecompressedImage::Format format;
  switch (embedded->component_count()) {
    case 1:
      format = DecompressedImage::Format::kGrey;
      break;
    case 3:
      format = DecompressedImage::Format::kRGB;
      break;
    case 4:
      format = DecompressedImage::Format::kRGBA;
      break;
    default:
      FML_LOG(WARNING) << "Textures with " << embedded->component_count()
                       << " components are not supported." << std::endl;
      return nullptr;
  }
  if (embedded->bytes()->size() != bytes_per_component *
                                       embedded->component_count() *
                                       embedded->width() * embedded->height()) {
    FML_LOG(WARNING) << "Embedded texture has an unexpected size. Skipping."
                     << std::endl;
    return nullptr;
  }

  auto image_mapping = std::make_shared<fml::NonOwnedMapping>(
      embedded->bytes()->Data(), embedded->bytes()->size());
  auto decompressed_image =
      DecompressedImage(ISize(embedded->width(), embedded->height()), format,
                        image_mapping)
          .ConvertToRGBA();

  auto texture_descriptor = TextureDescriptor{};
  texture_descriptor.storage_mode = StorageMode::kHostVisible;
  texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
  texture_descriptor.size = decompressed_image.GetSize();
  // TODO(bdero): Generate mipmaps for embedded textures.
  texture_descriptor.mip_count = 1u;

  auto texture = allocator.CreateTexture(texture_descriptor);
  if (!texture) {
    FML_LOG(ERROR) << "Could not allocate texture.";
    return nullptr;
  }

  auto uploaded = texture->SetContents(decompressed_image.GetAllocation());
  if (!uploaded) {
    FML_LOG(ERROR) << "Could not upload texture to device memory.";
    return nullptr;
  }

  return texture;
}

std::shared_ptr<Node> Node::MakeFromFlatbuffer(const fb::Scene& scene,
                                               Allocator& allocator) {
  // Unpack textures.
  std::vector<std::shared_ptr<Texture>> textures;
  if (scene.textures()) {
    for (const auto iptexture : *scene.textures()) {
      // The elements of the unpacked texture array must correspond exactly with
      // the ipscene texture array. So if a texture is empty or invalid, a
      // nullptr is inserted as a placeholder.
      textures.push_back(UnpackTextureFromFlatbuffer(iptexture, allocator));
    }
  }

  auto result = std::make_shared<Node>();
  result->SetLocalTransform(importer::ToMatrix(*scene.transform()));

  if (!scene.nodes() || !scene.children()) {
    return result;  // The scene is empty.
  }

  // Initialize nodes for unpacking the entire scene.
  std::vector<std::shared_ptr<Node>> scene_nodes;
  scene_nodes.reserve(scene.nodes()->size());
  for (size_t node_i = 0; node_i < scene.nodes()->size(); node_i++) {
    scene_nodes.push_back(std::make_shared<Node>());
  }

  // Connect children to the root node.
  for (int child : *scene.children()) {
    if (child < 0 || static_cast<size_t>(child) >= scene_nodes.size()) {
      VALIDATION_LOG << "Scene child index out of range.";
      continue;
    }
    result->AddChild(scene_nodes[child]);
  }

  // Unpack each node.
  for (size_t node_i = 0; node_i < scene.nodes()->size(); node_i++) {
    scene_nodes[node_i]->UnpackFromFlatbuffer(*scene.nodes()->Get(node_i),
                                              scene_nodes, textures, allocator);
  }

  // Unpack animations.
  if (scene.animations()) {
    for (const auto animation : *scene.animations()) {
      if (auto out_animation =
              Animation::MakeFromFlatbuffer(*animation, scene_nodes)) {
        result->animations_.push_back(out_animation);
      }
    }
  }

  return result;
}

void Node::UnpackFromFlatbuffer(
    const fb::Node& source_node,
    const std::vector<std::shared_ptr<Node>>& scene_nodes,
    const std::vector<std::shared_ptr<Texture>>& textures,
    Allocator& allocator) {
  name_ = source_node.name()->str();
  SetLocalTransform(importer::ToMatrix(*source_node.transform()));

  /// Meshes.

  if (source_node.mesh_primitives()) {
    Mesh mesh;
    for (const auto* primitives : *source_node.mesh_primitives()) {
      auto geometry = Geometry::MakeFromFlatbuffer(*primitives, allocator);
      auto material =
          primitives->material()
              ? Material::MakeFromFlatbuffer(*primitives->material(), textures)
              : Material::MakeUnlit();
      mesh.AddPrimitive({std::move(geometry), std::move(material)});
    }
    SetMesh(std::move(mesh));
  }

  /// Child nodes.

  if (source_node.children()) {
    // Wire up graph connections.
    for (int child : *source_node.children()) {
      if (child < 0 || static_cast<size_t>(child) >= scene_nodes.size()) {
        VALIDATION_LOG << "Node child index out of range.";
        continue;
      }
      AddChild(scene_nodes[child]);
    }
  }

  /// Skin.

  if (source_node.skin()) {
    skin_ = Skin::MakeFromFlatbuffer(*source_node.skin(), scene_nodes);
  }
}

Node::Node() : name_(SPrintF("__node%" PRIu64, kNextNodeID++)){};

Node::~Node() = default;

Mesh::Mesh(Mesh&& mesh) = default;

Mesh& Mesh::operator=(Mesh&& mesh) = default;

const std::string& Node::GetName() const {
  return name_;
}

void Node::SetName(const std::string& new_name) {
  name_ = new_name;
}

Node* Node::GetParent() const {
  return parent_;
}

std::shared_ptr<Node> Node::FindChildByName(
    const std::string& name,
    bool exclude_animation_players) const {
  for (auto& child : children_) {
    if (exclude_animation_players && child->animation_player_.has_value()) {
      continue;
    }
    if (child->GetName() == name) {
      return child;
    }
    if (auto found = child->FindChildByName(name)) {
      return found;
    }
  }
  return nullptr;
}

std::shared_ptr<Animation> Node::FindAnimationByName(
    const std::string& name) const {
  for (const auto& animation : animations_) {
    if (animation->GetName() == name) {
      return animation;
    }
  }
  return nullptr;
}

AnimationClip* Node::AddAnimation(const std::shared_ptr<Animation>& animation) {
  if (!animation_player_.has_value()) {
    animation_player_ = AnimationPlayer();
  }
  return animation_player_->AddAnimation(animation, this);
}

void Node::SetLocalTransform(Matrix transform) {
  local_transform_ = transform;
}

Matrix Node::GetLocalTransform() const {
  return local_transform_;
}

void Node::SetGlobalTransform(Matrix transform) {
  Matrix inverse_global_transform =
      parent_ ? parent_->GetGlobalTransform().Invert() : Matrix();

  local_transform_ = inverse_global_transform * transform;
}

Matrix Node::GetGlobalTransform() const {
  if (parent_) {
    return parent_->GetGlobalTransform() * local_transform_;
  }
  return local_transform_;
}

bool Node::AddChild(std::shared_ptr<Node> node) {
  if (!node) {
    VALIDATION_LOG << "Cannot add null child to node.";
    return false;
  }

  // TODO(bdero): Figure out a better paradigm/rules for nodes with multiple
  //              parents. We should probably disallow this, make deep
  //              copying of nodes cheap and easy, add mesh instancing, etc.
  //              Today, the parent link is only used for skin posing, and so
  //              it's reasonable to not have a check and allow multi-parenting.
  //              Even still, there should still be some kind of cycle
  //              prevention/detection, ideally at the protocol level.
  //
  // if (node->parent_ != nullptr) {
  //   VALIDATION_LOG
  //       << "Cannot add a node as a child which already has a parent.";
  //   return false;
  // }
  node->parent_ = this;
  children_.push_back(std::move(node));

  return true;
}

std::vector<std::shared_ptr<Node>>& Node::GetChildren() {
  return children_;
}

void Node::SetMesh(Mesh mesh) {
  mesh_ = std::move(mesh);
}

Mesh& Node::GetMesh() {
  return mesh_;
}

void Node::SetIsJoint(bool is_joint) {
  is_joint_ = is_joint;
}

bool Node::IsJoint() const {
  return is_joint_;
}

bool Node::Render(SceneEncoder& encoder,
                  Allocator& allocator,
                  const Matrix& parent_transform) {
  std::optional<std::vector<MutationLog::Entry>> log = mutation_log_.Flush();
  if (log.has_value()) {
    for (const auto& entry : log.value()) {
      if (auto e = std::get_if<MutationLog::SetTransformEntry>(&entry)) {
        local_transform_ = e->transform;
      } else if (auto e =
                     std::get_if<MutationLog::SetAnimationStateEntry>(&entry)) {
        AnimationClip* clip =
            animation_player_.has_value()
                ? animation_player_->GetClip(e->animation_name)
                : nullptr;
        if (!clip) {
          auto animation = FindAnimationByName(e->animation_name);
          if (!animation) {
            continue;
          }
          clip = AddAnimation(animation);
          if (!clip) {
            continue;
          }
        }

        clip->SetPlaying(e->playing);
        clip->SetLoop(e->loop);
        clip->SetWeight(e->weight);
        clip->SetPlaybackTimeScale(e->time_scale);
      } else if (auto e =
                     std::get_if<MutationLog::SeekAnimationEntry>(&entry)) {
        AnimationClip* clip =
            animation_player_.has_value()
                ? animation_player_->GetClip(e->animation_name)
                : nullptr;
        if (!clip) {
          auto animation = FindAnimationByName(e->animation_name);
          if (!animation) {
            continue;
          }
          clip = AddAnimation(animation);
          if (!clip) {
            continue;
          }
        }

        clip->Seek(SecondsF(e->time));
      }
    }
  }

  if (animation_player_.has_value()) {
    animation_player_->Update();
  }

  Matrix transform = parent_transform * local_transform_;
  mesh_.Render(encoder, transform,
               skin_ ? skin_->GetJointsTexture(allocator) : nullptr);

  for (auto& child : children_) {
    if (!child->Render(encoder, allocator, transform)) {
      return false;
    }
  }
  return true;
}

void Node::AddMutation(const MutationLog::Entry& entry) {
  mutation_log_.Append(entry);
}

}  // namespace scene
}  // namespace impeller
