// Copyright 2015 The Chromium 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 "services/gfx/compositor/graph/scene_def.h"

#include <ostream>
#include <utility>

#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
#include "mojo/services/gfx/composition/cpp/formatting.h"
#include "services/gfx/compositor/graph/snapshot.h"
#include "services/gfx/compositor/render/render_image.h"
#include "services/gfx/compositor/render/render_layer.h"

namespace compositor {

namespace {
// TODO(jeffbrown): Determine and document a more appropriate size limit
// for transferred images as part of the image pipe abstraction instead.
const int32_t kMaxTextureWidth = 65536;
const int32_t kMaxTextureHeight = 65536;

void ReleaseMailboxTexture(
    mojo::gfx::composition::MailboxTextureCallbackPtr callback) {
  if (callback)
    callback->OnMailboxTextureReleased();
}
}  // namespace

SceneDef::SceneDef(mojo::gfx::composition::SceneTokenPtr scene_token,
                   const std::string& label)
    : scene_token_(scene_token.Pass()), label_(label) {
  DCHECK(scene_token_);
}

SceneDef::~SceneDef() {}

void SceneDef::EnqueueUpdate(mojo::gfx::composition::SceneUpdatePtr update) {
  DCHECK(update);
  pending_updates_.push_back(update.Pass());
}

void SceneDef::EnqueuePublish(
    mojo::gfx::composition::SceneMetadataPtr metadata) {
  DCHECK(metadata);
  pending_publications_.emplace_back(new Publication(metadata.Pass()));
  pending_updates_.swap(pending_publications_.back()->updates);
}

SceneDef::Disposition SceneDef::Present(
    int64_t presentation_time,
    const SceneResolver& resolver,
    const SceneUnavailableSender& unavailable_sender,
    std::ostream& err) {
  // Walk backwards through the pending publications to find the index
  // just beyond the last one which is due to be presented at or before the
  // presentation time.
  size_t end = pending_publications_.size();
  for (;;) {
    if (!end)
      return Disposition::kUnchanged;
    if (pending_publications_[end - 1]->is_due(presentation_time))
      break;  // found last presentable publication
    end--;
  }

  // Prepare to apply all publications up to this point.
  uint32_t version = pending_publications_[end - 1]->metadata->version;
  if (version_ != version) {
    version_ = version;
    formatted_label_cache_.clear();
  }
  Invalidate();

  // Apply all updates sequentially.
  for (size_t index = 0; index < end; ++index) {
    for (auto& update : pending_publications_[index]->updates) {
      if (!ApplyUpdate(update.Pass(), resolver, unavailable_sender, err))
        return Disposition::kFailed;
    }
  }

  // Dequeue the publications we processed.
  pending_publications_.erase(pending_publications_.begin(),
                              pending_publications_.begin() + end);

  // Ensure the scene is in a valid state.
  if (!Validate(err))
    return Disposition::kFailed;
  return Disposition::kSucceeded;
}

bool SceneDef::ApplyUpdate(mojo::gfx::composition::SceneUpdatePtr update,
                           const SceneResolver& resolver,
                           const SceneUnavailableSender& unavailable_sender,
                           std::ostream& err) {
  DCHECK(update);

  // Update resources.
  if (update->clear_resources) {
    resources_.clear();
  }
  for (auto it = update->resources.begin(); it != update->resources.end();
       ++it) {
    uint32_t resource_id = it.GetKey();
    mojo::gfx::composition::ResourcePtr& resource_decl = it.GetValue();
    if (resource_decl) {
      ResourceDef* resource = CreateResource(resource_id, resource_decl.Pass(),
                                             resolver, unavailable_sender, err);
      if (!resource)
        return false;
      resources_[resource_id].reset(resource);
    } else {
      resources_.erase(resource_id);
    }
  }

  // Update nodes.
  if (update->clear_nodes) {
    nodes_.clear();
  }
  for (auto it = update->nodes.begin(); it != update->nodes.end(); ++it) {
    uint32_t node_id = it.GetKey();
    mojo::gfx::composition::NodePtr& node_decl = it.GetValue();
    if (node_decl) {
      NodeDef* node = CreateNode(node_id, node_decl.Pass(), err);
      if (!node)
        return false;
      nodes_[node_id].reset(node);
    } else {
      nodes_.erase(node_id);
    }
  }
  return true;
}

bool SceneDef::Validate(std::ostream& err) {
  // Validate all nodes.
  // TODO(jeffbrown): Figure out how to do this incrementally if it gets
  // too expensive to process all nodes each time.
  root_node_ = nullptr;
  for (auto& pair : nodes_) {
    uint32_t node_id = pair.first;
    NodeDef* node = pair.second.get();
    if (!node->Validate(this, err))
      return false;
    if (node_id == mojo::gfx::composition::kSceneRootNodeId)
      root_node_ = node;
  }
  return true;
}

bool SceneDef::UnlinkReferencedScene(
    SceneDef* scene,
    const SceneUnavailableSender& unavailable_sender) {
  DCHECK(scene);

  bool changed = false;
  for (auto& pair : resources_) {
    if (pair.second->type() == ResourceDef::Type::kScene) {
      auto scene_resource = static_cast<SceneResourceDef*>(pair.second.get());
      if (scene_resource->referenced_scene() == scene) {
        scene_resource->clear_referenced_scene();
        Invalidate();
        changed = true;
        unavailable_sender.Run(pair.first);
      }
    }
  }
  return changed;
}

bool SceneDef::Snapshot(SnapshotBuilder* snapshot_builder,
                        RenderLayerBuilder* layer_builder) {
  DCHECK(snapshot_builder);
  DCHECK(layer_builder);

  // Detect cycles.
  if (visited_) {
    if (snapshot_builder->block_log()) {
      *snapshot_builder->block_log()
          << "Scene blocked due to recursive cycle: " << FormattedLabel()
          << std::endl;
    }
    return false;
  }

  // Snapshot the contents of the scene.
  visited_ = true;
  bool success = SnapshotInner(snapshot_builder, layer_builder);
  visited_ = false;
  return success;
}

bool SceneDef::SnapshotInner(SnapshotBuilder* snapshot_builder,
                             RenderLayerBuilder* layer_builder) {
  // Note the dependency even if blocked.
  snapshot_builder->AddSceneDependency(this);

  // Ensure we have a root node.
  if (!root_node_) {
    if (snapshot_builder->block_log()) {
      *snapshot_builder->block_log()
          << "Scene blocked due because it has no root node: "
          << FormattedLabel() << std::endl;
    }
    return false;
  }

  // Snapshot and draw the layer.
  std::shared_ptr<RenderLayer> scene_layer = SnapshotLayer(snapshot_builder);
  if (!scene_layer)
    return false;
  layer_builder->DrawLayer(scene_layer);
  return true;
}

std::shared_ptr<RenderLayer> SceneDef::SnapshotLayer(
    SnapshotBuilder* snapshot_builder) {
  if (cached_layer_)
    return cached_layer_;

  RenderLayerBuilder scene_layer_builder;
  scene_layer_builder.PushScene(scene_token_->value, version_);
  if (!root_node_->Snapshot(snapshot_builder, &scene_layer_builder, this))
    return nullptr;
  scene_layer_builder.PopScene();

  // TODO(jeffbrown): Implement caching even when the scene has dependencies.
  // There are some subtleties to be dealt with to ensure that caches
  // are properly invalidated and that we don't accidentally cache layers which
  // bake in decisions which counteract the intended cycle detection and
  // avoidance behavior.  Basically just need better bookkeeping.
  std::shared_ptr<RenderLayer> scene_layer = scene_layer_builder.Build();
  if (!HasSceneResources())
    cached_layer_ = scene_layer;
  return scene_layer;
}

void SceneDef::Invalidate() {
  cached_layer_.reset();
}

bool SceneDef::HasSceneResources() {
  for (auto& pair : resources_) {
    if (pair.second->type() == ResourceDef::Type::kScene)
      return true;
  }
  return false;
}

ResourceDef* SceneDef::CreateResource(
    uint32_t resource_id,
    mojo::gfx::composition::ResourcePtr resource_decl,
    const SceneResolver& resolver,
    const SceneUnavailableSender& unavailable_sender,
    std::ostream& err) {
  DCHECK(resource_decl);

  if (resource_decl->is_scene()) {
    auto& scene_resource_decl = resource_decl->get_scene();
    DCHECK(scene_resource_decl->scene_token);
    SceneDef* referenced_scene =
        resolver.Run(scene_resource_decl->scene_token.get());
    if (!referenced_scene) {
      unavailable_sender.Run(resource_id);
    }
    return new SceneResourceDef(referenced_scene);
  }

  if (resource_decl->is_mailbox_texture()) {
    auto& mailbox_texture_resource_decl = resource_decl->get_mailbox_texture();
    DCHECK(mailbox_texture_resource_decl->mailbox_name.size() ==
           GL_MAILBOX_SIZE_CHROMIUM);
    DCHECK(mailbox_texture_resource_decl->size);
    int32_t width = mailbox_texture_resource_decl->size->width;
    int32_t height = mailbox_texture_resource_decl->size->height;
    if (width < 1 || width > kMaxTextureWidth || height < 1 ||
        height > kMaxTextureHeight) {
      err << "MailboxTexture resource has invalid size: "
          << "resource_id=" << resource_id << ", width=" << width
          << ", height=" << height;
      return nullptr;
    }
    std::shared_ptr<RenderImage> image = RenderImage::CreateFromMailboxTexture(
        reinterpret_cast<GLbyte*>(
            mailbox_texture_resource_decl->mailbox_name.data()),
        mailbox_texture_resource_decl->sync_point, width, height,
        base::MessageLoop::current()->task_runner(),
        base::Bind(
            &ReleaseMailboxTexture,
            base::Passed(
                mojo::gfx::composition::MailboxTextureCallbackPtr::Create(
                    std::move(mailbox_texture_resource_decl->callback)))));
    if (!image) {
      err << "Could not create MailboxTexture";
      return nullptr;
    }
    return new ImageResourceDef(image);
  }

  err << "Unsupported resource type: resource_id=" << resource_id;
  return nullptr;
}

NodeDef* SceneDef::CreateNode(uint32_t node_id,
                              mojo::gfx::composition::NodePtr node_decl,
                              std::ostream& err) {
  DCHECK(node_decl);

  NodeOp* op = nullptr;
  if (node_decl->op) {
    op = CreateNodeOp(node_id, node_decl->op.Pass(), err);
    if (!op)
      return nullptr;
  }

  return new NodeDef(node_id, node_decl->content_transform.Pass(),
                     node_decl->content_clip.Pass(), node_decl->hit_id,
                     node_decl->combinator, node_decl->child_node_ids.storage(),
                     op);
}

NodeOp* SceneDef::CreateNodeOp(uint32_t node_id,
                               mojo::gfx::composition::NodeOpPtr node_op_decl,
                               std::ostream& err) {
  DCHECK(node_op_decl);

  if (node_op_decl->is_rect()) {
    auto& rect_node_op_decl = node_op_decl->get_rect();
    DCHECK(rect_node_op_decl->content_rect);
    DCHECK(rect_node_op_decl->color);
    return new RectNodeOp(*rect_node_op_decl->content_rect,
                          *rect_node_op_decl->color);
  }

  if (node_op_decl->is_image()) {
    auto& image_node_op_decl = node_op_decl->get_image();
    DCHECK(image_node_op_decl->content_rect);
    return new ImageNodeOp(*image_node_op_decl->content_rect,
                           image_node_op_decl->image_rect.Pass(),
                           image_node_op_decl->image_resource_id,
                           image_node_op_decl->blend.Pass());
  }

  if (node_op_decl->is_scene()) {
    auto& scene_node_op_decl = node_op_decl->get_scene();
    return new SceneNodeOp(scene_node_op_decl->scene_resource_id,
                           scene_node_op_decl->scene_version);
  }

  if (node_op_decl->is_layer()) {
    auto& layer_node_op_decl = node_op_decl->get_layer();
    DCHECK(layer_node_op_decl->layer_size);
    return new LayerNodeOp(*layer_node_op_decl->layer_size,
                           layer_node_op_decl->blend.Pass());
  }

  err << "Unsupported node op type: node_id=" << node_id
      << ", node_op=" << node_op_decl;
  return nullptr;
}

NodeDef* SceneDef::FindNode(uint32_t node_id) {
  auto it = nodes_.find(node_id);
  return it != nodes_.end() ? it->second.get() : nullptr;
}

ResourceDef* SceneDef::FindResource(uint32_t resource_id,
                                    ResourceDef::Type resource_type) {
  auto it = resources_.find(resource_id);
  return it != resources_.end() && it->second->type() == resource_type
             ? it->second.get()
             : nullptr;
}

std::string SceneDef::FormattedLabel() {
  if (formatted_label_cache_.empty()) {
    formatted_label_cache_ =
        label_.empty()
            ? base::StringPrintf("<%d/%d>", scene_token_->value, version_)
            : base::StringPrintf("<%d:%s/%d>", scene_token_->value,
                                 label_.c_str(), version_);
  }
  return formatted_label_cache_;
}

SceneDef::Publication::Publication(
    mojo::gfx::composition::SceneMetadataPtr metadata)
    : metadata(metadata.Pass()) {
  DCHECK(this->metadata);
}

SceneDef::Publication::~Publication() {}

}  // namespace compositor
