// Copyright 2017 The Fuchsia 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 "garnet/bin/ui/sketchy/canvas.h"

#include <trace/event.h>

#include "garnet/bin/ui/sketchy/frame.h"
#include "garnet/bin/ui/sketchy/resources/import_node.h"
#include "garnet/bin/ui/sketchy/resources/stroke.h"
#include "src/ui/lib/escher/util/fuchsia_utils.h"

namespace sketchy_service {

CanvasImpl::CanvasImpl(async::Loop* loop, scenic::Session* session,
                       escher::EscherWeakPtr weak_escher)
    : loop_(loop),
      session_(session),
      escher_(weak_escher),
      buffer_factory_(weak_escher->gpu_allocator(),
                      weak_escher->resource_recycler()),
      shared_buffer_pool_(session, &buffer_factory_),
      stroke_manager_(std::move(weak_escher)) {}

void CanvasImpl::Init(
    fidl::InterfaceHandle<::fuchsia::ui::sketchy::CanvasListener> listener) {
  // TODO(SCN-269): unimplemented.
  FXL_LOG(ERROR) << "Init: unimplemented.";
}

void CanvasImpl::Enqueue(
    std::vector<::fuchsia::ui::sketchy::Command> commands) {
  // TODO: Use `AddAll()` when fidl::VectorPtr supports it.
  for (size_t i = 0; i < commands.size(); ++i) {
    commands_.push_back(std::move(commands.at(i)));
  }
}

void CanvasImpl::Present(uint64_t presentation_time, PresentCallback callback) {
  TRACE_DURATION("gfx", "CanvasImpl::Present");
  TRACE_FLOW_END("gfx", "PresentCanvas", canvas_present_count_);
  ++canvas_present_count_;
  TRACE_FLOW_BEGIN("gfx", "RequestScenicPresent",
                   request_scenic_present_count_);

  // TODO(SCN-269): Present() should behave the same way as Scenic.
  // Specifically, Commands shouldn't be applied immediately. Instead a
  // frame-request should be triggered and the Commands enqueue; when the
  // corresponding frame is processed all Commands that are scheduled for the
  // current frame's presentation time are applied.
  for (auto it = commands_->begin(); it != commands_->end(); ++it) {
    if (!ApplyCommand(std::move(*it))) {
      loop_->Quit();
    }
  }
  commands_.reset();
  callbacks_.push_back(std::move(callback));
  RequestScenicPresent(presentation_time);
}

void CanvasImpl::RequestScenicPresent(uint64_t presentation_time) {
  TRACE_DURATION("gfx", "CanvasImpl::RequestScenicPresent");
  if (is_scenic_present_requested_) {
    return;
  }
  is_scenic_present_requested_ = true;

  auto session_callback = [this, callbacks = std::move(callbacks_)](
                              fuchsia::images::PresentationInfo info) {
    FXL_DCHECK(is_scenic_present_requested_);
    is_scenic_present_requested_ = false;
    for (auto& callback : callbacks) {
      callback(info);
    }
    RequestScenicPresent(info.presentation_time + info.presentation_interval);
  };
  callbacks_.clear();

  TRACE_FLOW_END("gfx", "RequestScenicPresent", request_scenic_present_count_);
  ++request_scenic_present_count_;
  TRACE_FLOW_BEGIN("gfx", "Session::Present", session_present_count_);
  ++session_present_count_;

  auto frame = Frame(escher_.get(), &shared_buffer_pool_, &buffer_factory_);
  if (frame.init_failed()) {
    session_->Present(presentation_time, std::move(session_callback));
    return;
  }

  stroke_manager_.Update(&frame);
  frame.RequestScenicPresent(session_, presentation_time,
                             std::move(session_callback));
}

bool CanvasImpl::ApplyCommand(::fuchsia::ui::sketchy::Command command) {
  switch (command.Which()) {
    case ::fuchsia::ui::sketchy::Command::Tag::kCreateResource:
      return ApplyCreateResourceCmd(std::move(command.create_resource()));
    case ::fuchsia::ui::sketchy::Command::Tag::kReleaseResource:
      return ApplyReleaseResourceCmd(std::move(command.release_resource()));
    case ::fuchsia::ui::sketchy::Command::Tag::kSetPath:
      return ApplySetPathCmd(std::move(command.set_path()));
    case ::fuchsia::ui::sketchy::Command::Tag::kAddStroke:
      return ApplyAddStrokeCmd(std::move(command.add_stroke()));
    case ::fuchsia::ui::sketchy::Command::Tag::kRemoveStroke:
      return ApplyRemoveStrokeCmd(std::move(command.remove_stroke()));
    case ::fuchsia::ui::sketchy::Command::Tag::kBeginStroke:
      return ApplyBeginStrokeCmd(std::move(command.begin_stroke()));
    case ::fuchsia::ui::sketchy::Command::Tag::kExtendStroke:
      return ApplyExtendStrokeCmd(std::move(command.extend_stroke()));
    case ::fuchsia::ui::sketchy::Command::Tag::kFinishStroke:
      return ApplyFinishStrokeCmd(std::move(command.finish_stroke()));
    case ::fuchsia::ui::sketchy::Command::Tag::kClearGroup:
      return ApplyClearGroupCmd(std::move(command.clear_group()));
    case ::fuchsia::ui::sketchy::Command::Tag::kScenicImportResource:
      return ApplyScenicImportResourceCmd(
          std::move(command.scenic_import_resource()));
    case ::fuchsia::ui::sketchy::Command::Tag::kScenicAddChild:
      return ApplyScenicAddChildCmd(std::move(command.scenic_add_child()));
    default:
      FXL_DCHECK(false) << "Unsupported op: "
                        << static_cast<uint32_t>(command.Which());
      return false;
  }
}

bool CanvasImpl::ApplyCreateResourceCmd(
    ::fuchsia::ui::sketchy::CreateResourceCmd create_resource) {
  switch (create_resource.args.Which()) {
    case ::fuchsia::ui::sketchy::ResourceArgs::Tag::kStroke:
      return CreateStroke(create_resource.id, create_resource.args.stroke());
    case ::fuchsia::ui::sketchy::ResourceArgs::Tag::kStrokeGroup:
      return CreateStrokeGroup(create_resource.id,
                               create_resource.args.stroke_group());
    default:
      FXL_DCHECK(false) << "Unsupported resource: "
                        << static_cast<uint32_t>(create_resource.args.Which());
      return false;
  }
}

bool CanvasImpl::CreateStroke(ResourceId id,
                              ::fuchsia::ui::sketchy::Stroke stroke) {
  return resource_map_.AddResource(
      id, fxl::MakeRefCounted<Stroke>(stroke_manager_.stroke_tessellator(),
                                      &buffer_factory_));
}

bool CanvasImpl::CreateStrokeGroup(
    ResourceId id, ::fuchsia::ui::sketchy::StrokeGroup stroke_group) {
  return resource_map_.AddResource(id,
                                   fxl::MakeRefCounted<StrokeGroup>(session_));
}

bool CanvasImpl::ApplyReleaseResourceCmd(
    ::fuchsia::ui::sketchy::ReleaseResourceCmd command) {
  return resource_map_.RemoveResource(command.id);
}

bool CanvasImpl::ApplySetPathCmd(
    ::fuchsia::ui::sketchy::SetStrokePathCmd command) {
  auto stroke = resource_map_.FindResource<Stroke>(command.stroke_id);
  if (!stroke) {
    FXL_LOG(ERROR) << "No Stroke of id " << command.stroke_id << " was found!";
    return false;
  }
  return stroke_manager_.SetStrokePath(
      stroke, std::make_unique<StrokePath>(std::move(command.path)));
}

bool CanvasImpl::ApplyAddStrokeCmd(
    ::fuchsia::ui::sketchy::AddStrokeCmd command) {
  auto stroke = resource_map_.FindResource<Stroke>(command.stroke_id);
  if (!stroke) {
    FXL_LOG(ERROR) << "No Stroke of id " << command.stroke_id << " was found!";
    return false;
  }
  auto group = resource_map_.FindResource<StrokeGroup>(command.group_id);
  if (!group) {
    FXL_LOG(ERROR) << "No StrokeGroup of id " << command.group_id
                   << " was found!";
    return false;
  }
  return stroke_manager_.AddStrokeToGroup(stroke, group);
}

bool CanvasImpl::ApplyRemoveStrokeCmd(
    ::fuchsia::ui::sketchy::RemoveStrokeCmd command) {
  auto stroke = resource_map_.FindResource<Stroke>(command.stroke_id);
  if (!stroke) {
    FXL_LOG(ERROR) << "No Stroke of id " << command.stroke_id << " was found!";
    return false;
  }
  auto group = resource_map_.FindResource<StrokeGroup>(command.group_id);
  if (!group) {
    FXL_LOG(ERROR) << "No StrokeGroup of id " << command.group_id
                   << " was found!";
    return false;
  }
  return stroke_manager_.RemoveStrokeFromGroup(stroke, group);
}

bool CanvasImpl::ApplyBeginStrokeCmd(
    ::fuchsia::ui::sketchy::BeginStrokeCmd command) {
  auto stroke = resource_map_.FindResource<Stroke>(command.stroke_id);
  if (!stroke) {
    FXL_LOG(ERROR) << "No Stroke of id " << command.stroke_id << " was found!";
    return false;
  }
  const auto& pos = command.touch.position;
  return stroke_manager_.BeginStroke(stroke, {pos.x, pos.y});
}

bool CanvasImpl::ApplyExtendStrokeCmd(
    ::fuchsia::ui::sketchy::ExtendStrokeCmd command) {
  auto stroke = resource_map_.FindResource<Stroke>(command.stroke_id);
  if (!stroke) {
    FXL_LOG(ERROR) << "No Stroke of id " << command.stroke_id << " was found!";
    return false;
  }
  std::vector<glm::vec2> pts;
  pts.reserve(command.touches.size());
  for (const auto& touch : command.touches) {
    pts.push_back({touch.position.x, touch.position.y});
  }
  return stroke_manager_.ExtendStroke(stroke, std::move(pts));
}

bool CanvasImpl::ApplyFinishStrokeCmd(
    ::fuchsia::ui::sketchy::FinishStrokeCmd command) {
  auto stroke = resource_map_.FindResource<Stroke>(command.stroke_id);
  if (!stroke) {
    FXL_LOG(ERROR) << "No Stroke of id " << command.stroke_id << " was found!";
    return false;
  }
  return stroke_manager_.FinishStroke(stroke);
}

bool CanvasImpl::ApplyClearGroupCmd(
    ::fuchsia::ui::sketchy::ClearGroupCmd command) {
  auto group = resource_map_.FindResource<StrokeGroup>(command.group_id);
  if (!group) {
    FXL_LOG(ERROR) << "No Group of id " << command.group_id << " was found!";
    return false;
  }
  return stroke_manager_.ClearGroup(group);
}

bool CanvasImpl::ApplyScenicImportResourceCmd(
    fuchsia::ui::gfx::ImportResourceCmd import_resource) {
  switch (import_resource.spec) {
    case fuchsia::ui::gfx::ImportSpec::NODE:
      return ScenicImportNode(import_resource.id,
                              std::move(import_resource.token));
  }
}

bool CanvasImpl::ScenicImportNode(ResourceId id, zx::eventpair token) {
  // As a client of Scenic, Canvas creates an ImportNode given token.
  auto node = fxl::MakeRefCounted<ImportNode>(session_, std::move(token));
  resource_map_.AddResource(id, std::move(node));
  return true;
}

bool CanvasImpl::ApplyScenicAddChildCmd(
    fuchsia::ui::gfx::AddChildCmd add_child) {
  auto import_node = resource_map_.FindResource<ImportNode>(add_child.node_id);
  auto stroke_group =
      resource_map_.FindResource<StrokeGroup>(add_child.child_id);
  if (!import_node || !stroke_group) {
    return false;
  }
  import_node->AddChild(stroke_group);
  return stroke_manager_.AddNewGroup(stroke_group);
}

}  // namespace sketchy_service
