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

#include <zircon/types.h>

#include <algorithm>  // For std::remove_if
#include <memory>

#include "flutter/fml/logging.h"

namespace flutter_runner::testing {

FakeFlatland::FakeFlatland()
    : allocator_binding_(this),
      flatland_binding_(this),
      present_handler_([](auto args) {}) {}

FakeFlatland::~FakeFlatland() = default;

fuchsia::ui::composition::AllocatorHandle FakeFlatland::ConnectAllocator(
    async_dispatcher_t* dispatcher) {
  FML_CHECK(!allocator_binding_.is_bound());

  fuchsia::ui::composition::AllocatorHandle allocator;
  allocator_binding_.Bind(allocator.NewRequest(), dispatcher);

  return allocator;
}

fuchsia::ui::composition::FlatlandHandle FakeFlatland::ConnectFlatland(
    async_dispatcher_t* dispatcher) {
  FML_CHECK(!flatland_binding_.is_bound());

  fuchsia::ui::composition::FlatlandHandle flatland;
  flatland_binding_.Bind(flatland.NewRequest(), dispatcher);

  return flatland;
}

void FakeFlatland::Disconnect(fuchsia::ui::composition::FlatlandError error) {
  flatland_binding_.events().OnError(std::move(error));
  flatland_binding_.Unbind();
  allocator_binding_
      .Unbind();  // TODO(fxb/85619): Does the real Scenic unbind this when
                  // Flatland has an error?  Or is it independent?
}

void FakeFlatland::SetPresentHandler(PresentHandler present_handler) {
  present_handler_ =
      present_handler ? std::move(present_handler) : [](auto args) {};
}

void FakeFlatland::FireOnNextFrameBeginEvent(
    fuchsia::ui::composition::OnNextFrameBeginValues
        on_next_frame_begin_values) {
  flatland_binding_.events().OnNextFrameBegin(
      std::move(on_next_frame_begin_values));
}

void FakeFlatland::FireOnFramePresentedEvent(
    fuchsia::scenic::scheduling::FramePresentedInfo frame_presented_info) {
  flatland_binding_.events().OnFramePresented(std::move(frame_presented_info));
}

void FakeFlatland::NotImplemented_(const std::string& name) {
  FML_LOG(FATAL) << "FakeFlatland does not implement " << name;
}

void FakeFlatland::RegisterBufferCollection(
    fuchsia::ui::composition::RegisterBufferCollectionArgs args,
    RegisterBufferCollectionCallback callback) {
  auto [export_token_koid, _] = GetKoids(args.export_token());
  auto [__, emplace_binding_success] =
      graph_bindings_.buffer_collections.emplace(
          export_token_koid,
          BufferCollectionBinding{
              .export_token = std::move(*args.mutable_export_token()),
              .sysmem_token =
                  std::move(*args.mutable_buffer_collection_token()),
              .usage = args.usage(),
          });
  // TODO(fxb/85619): Disconnect the Allocator here
  FML_CHECK(emplace_binding_success)
      << "FakeFlatland::RegisterBufferCollection: BufferCollection already "
         "exists with koid "
      << export_token_koid;
}

void FakeFlatland::Present(fuchsia::ui::composition::PresentArgs args) {
  // Each FIDL call between this `Present()` and the last one mutated the
  // `pending_graph_` independently of the `current_graph_`.  Only the
  // `current_graph_` is visible externally in the test.
  //
  // `Present()` updates the current graph with a deep clone of the pending one.
  current_graph_ = pending_graph_.Clone();

  present_handler_(std::move(args));
}

void FakeFlatland::CreateView(
    fuchsia::ui::views::ViewCreationToken token,
    fidl::InterfaceRequest<fuchsia::ui::composition::ParentViewportWatcher>
        parent_viewport_watcher) {
  CreateView2(std::move(token), fuchsia::ui::views::ViewIdentityOnCreation{},
              fuchsia::ui::composition::ViewBoundProtocols{},
              std::move(parent_viewport_watcher));
}

void FakeFlatland::CreateView2(
    fuchsia::ui::views::ViewCreationToken token,
    fuchsia::ui::views::ViewIdentityOnCreation view_identity,
    fuchsia::ui::composition::ViewBoundProtocols view_protocols,
    fidl::InterfaceRequest<fuchsia::ui::composition::ParentViewportWatcher>
        parent_viewport_watcher) {
  // TODO(fxb/85619): Handle a 2nd CreateView call
  FML_CHECK(!pending_graph_.view.has_value());
  FML_CHECK(!graph_bindings_.viewport_watcher.has_value());

  auto view_token_koids = GetKoids(token);
  auto view_ref_koids = GetKoids(view_identity.view_ref);
  auto view_ref_control_koids = GetKoids(view_identity.view_ref_control);
  FML_CHECK(view_ref_koids.first == view_ref_control_koids.second);
  FML_CHECK(view_ref_koids.second == view_ref_control_koids.first);

  pending_graph_.view.emplace(FakeView{
      .view_token = view_token_koids.first,
      .view_ref = view_ref_koids.first,
      .view_ref_control = view_ref_control_koids.first,
      .view_ref_focused =
          view_protocols.has_view_ref_focused()
              ? GetKoids(view_protocols.view_ref_focused()).first
              : zx_koid_t{},
      .focuser = view_protocols.has_view_focuser()
                     ? GetKoids(view_protocols.view_focuser()).first
                     : zx_koid_t{},
      .touch_source = view_protocols.has_touch_source()
                          ? GetKoids(view_protocols.touch_source()).first
                          : zx_koid_t{},
      .mouse_source = view_protocols.has_mouse_source()
                          ? GetKoids(view_protocols.mouse_source()).first
                          : zx_koid_t{},
      .parent_viewport_watcher = GetKoids(parent_viewport_watcher).first,
  });
  graph_bindings_.viewport_watcher.emplace(
      view_token_koids.first,
      ParentViewportWatcher(
          std::move(token), std::move(view_identity), std::move(view_protocols),
          std::move(parent_viewport_watcher), flatland_binding_.dispatcher()));
}

void FakeFlatland::CreateTransform(
    fuchsia::ui::composition::TransformId transform_id) {
  if (transform_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::CreateTransform: TransformId 0 is invalid.";
    return;
  }
  if (pending_graph_.transform_map.count(transform_id.value) != 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::CreateTransform: TransformId "
                     << transform_id.value << " is already in use.";
    return;
  }

  auto [emplaced_transform, emplace_success] =
      pending_graph_.transform_map.emplace(
          transform_id.value, std::make_shared<FakeTransform>(FakeTransform{
                                  .id = transform_id,
                              }));
  // TODO(fxb/85619): Raise a FlatlandError here
  FML_CHECK(emplace_success)
      << "FakeFlatland::CreateTransform: Internal error (transform_map) adding "
         "transform with id: "
      << transform_id.value;

  auto [_, emplace_parent_success] = parents_map_.emplace(
      transform_id.value,
      std::make_pair(std::weak_ptr<FakeTransform>(),
                     std::weak_ptr(emplaced_transform->second)));
  // TODO(fxb/85619): Raise a FlatlandError here
  FML_CHECK(emplace_parent_success)
      << "FakeFlatland::CreateTransform: Internal error (parent_map) adding "
         "transform with id: "
      << transform_id.value;
}

void FakeFlatland::SetTranslation(
    fuchsia::ui::composition::TransformId transform_id,
    fuchsia::math::Vec translation) {
  if (transform_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::SetTranslation: TransformId 0 is invalid.";
    return;
  }

  auto found_transform = pending_graph_.transform_map.find(transform_id.value);
  if (found_transform == pending_graph_.transform_map.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::SetTranslation: TransformId "
                     << transform_id.value << " does not exist.";
    return;
  }

  auto& transform = found_transform->second;
  FML_CHECK(transform);
  transform->translation = translation;
}

void FakeFlatland::SetOrientation(
    fuchsia::ui::composition::TransformId transform_id,
    fuchsia::ui::composition::Orientation orientation) {
  if (transform_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::SetOrientation: TransformId 0 is invalid.";
    return;
  }

  auto found_transform = pending_graph_.transform_map.find(transform_id.value);
  if (found_transform == pending_graph_.transform_map.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::SetOrientation: TransformId "
                     << transform_id.value << " does not exist.";
    return;
  }

  auto& transform = found_transform->second;
  FML_CHECK(transform);
  transform->orientation = orientation;
}

void FakeFlatland::SetClipBounds(
    fuchsia::ui::composition::TransformId transform_id,
    fuchsia::math::Rect clip_bounds) {
  if (transform_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::SetClipBounds: TransformId 0 is invalid.";
    return;
  }

  auto found_transform = pending_graph_.transform_map.find(transform_id.value);
  if (found_transform == pending_graph_.transform_map.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::SetClipBounds: TransformId "
                     << transform_id.value << " does not exist.";
    return;
  }

  auto& transform = found_transform->second;
  FML_CHECK(transform);
  transform->clip_bounds = clip_bounds;
}

// TODO(fxbug.dev/89111): Re-enable once SDK rolls.
// void FakeFlatland::SetImageOpacity(
//     fuchsia::ui::composition::ContentId content_id,
//     float opacity) {
//   if (content_id.value == 0) {
//     // TODO(fxb/85619): Raise a FlatlandError here
//     FML_CHECK(false)
//         << "FakeFlatland::SetImageOpacity: ContentId 0 is invalid.";
//     return;
//   }

//   auto found_content = pending_graph_.content_map.find(image_id.value);
//   if (found_content == pending_graph_.content_map.end()) {
//     // TODO(fxb/85619): Raise a FlatlandError here
//     FML_CHECK(false) << "FakeFlatland::SetImageOpacity: ContentId "
//                      << image_id.value << " does not exist.";
//     return;
//   }

//   auto& content = found_content->second;
//   FML_CHECK(content);
//   FakeImage* image = std::get_if<FakeImage>(content.get());
//   if (image == nullptr) {
//     // TODO(fxb/85619): Raise a FlatlandError here
//     FML_CHECK(false) << "FakeFlatland::SetImageOpacity: ContentId "
//                      << image_id.value << " is not an Image.";
//     return;
//   }

//   image->opacity = opacity;
// }

void FakeFlatland::AddChild(
    fuchsia::ui::composition::TransformId parent_transform_id,
    fuchsia::ui::composition::TransformId child_transform_id) {
  if (parent_transform_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::AddChild: Parent TransformId 0 is invalid.";
    return;
  }
  if (child_transform_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::AddChild: Child TransformId 0 is invalid.";
    return;
  }

  auto found_parent =
      pending_graph_.transform_map.find(parent_transform_id.value);
  if (found_parent == pending_graph_.transform_map.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::AddChild: Parent TransformId "
                     << parent_transform_id.value << " does not exist.";
    return;
  }
  auto found_child =
      pending_graph_.transform_map.find(child_transform_id.value);
  if (found_child == pending_graph_.transform_map.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::AddChild: Child TransformId "
                     << child_transform_id.value << " does not exist.";
    return;
  }
  auto found_child_old_parent = parents_map_.find(child_transform_id.value);
  if (found_child_old_parent == parents_map_.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::AddChild: Internal error - Child TransformId "
        << child_transform_id.value << " is not in parents_map.";
    return;
  }
  if (found_child_old_parent->second.second.expired()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::AddChild: Internal error - Child TransformId "
        << child_transform_id.value << " is expired in parents_map.";
    return;
  }

  auto& child = found_child->second;
  auto& new_parent = found_parent->second;
  new_parent->children.push_back(child);
  if (auto old_parent = found_child_old_parent->second.first.lock()) {
    old_parent->children.erase(std::remove_if(
        old_parent->children.begin(), old_parent->children.end(),
        [&child](const auto& transform) { return transform == child; }));
  }
  found_child_old_parent->second.first = std::weak_ptr(new_parent);
}

void FakeFlatland::RemoveChild(
    fuchsia::ui::composition::TransformId parent_transform_id,
    fuchsia::ui::composition::TransformId child_transform_id) {
  if (parent_transform_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::RemoveChild: Parent TransformId 0 is invalid.";
    return;
  }
  if (child_transform_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::RemoveChild: Child TransformId 0 is invalid.";
    return;
  }

  auto found_child =
      pending_graph_.transform_map.find(child_transform_id.value);
  if (found_child == pending_graph_.transform_map.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::RemoveChild: Child TransformId "
                     << child_transform_id.value << " does not exist.";
    return;
  }

  auto found_parent =
      pending_graph_.transform_map.find(parent_transform_id.value);
  if (found_parent == pending_graph_.transform_map.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::RemoveChild: Parent TransformId "
                     << parent_transform_id.value << " does not exist.";
    return;
  }

  auto found_child_parent = parents_map_.find(child_transform_id.value);
  if (found_child_parent == parents_map_.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::RemoveChild: Internal error - Child TransformId "
        << child_transform_id.value << " is not in parents_map.";
    return;
  }
  if (found_child_parent->second.second.expired()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::RemoveChild: Internal error - Child TransformId "
        << child_transform_id.value << " is expired in parents_map.";
    return;
  }
  if (found_child_parent->second.first.lock() != found_parent->second) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::RemoveChild: Internal error - Child TransformId "
        << child_transform_id.value << " is not a child of Parent TransformId "
        << parent_transform_id.value << ".";
    return;
  }

  found_child_parent->second.first = std::weak_ptr<FakeTransform>();
  found_parent->second->children.erase(std::remove_if(
      found_parent->second->children.begin(),
      found_parent->second->children.end(),
      [child_to_remove = found_child->second](const auto& child) {
        return child == child_to_remove;
      }));
}

void FakeFlatland::SetContent(
    fuchsia::ui::composition::TransformId transform_id,
    fuchsia::ui::composition::ContentId content_id) {
  if (transform_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::SetContent: TransformId 0 is invalid.";
    return;
  }

  auto found_transform = pending_graph_.transform_map.find(transform_id.value);
  if (found_transform == pending_graph_.transform_map.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::SetContent: TransformId "
                     << transform_id.value << " does not exist.";
    return;
  }

  auto& transform = found_transform->second;
  FML_CHECK(transform);
  if (content_id.value == 0) {
    transform->content.reset();
    return;
  }

  auto found_content = pending_graph_.content_map.find(content_id.value);
  if (found_content == pending_graph_.content_map.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::SetContent: ContentId "
                     << content_id.value << " does not exist.";
    return;
  }

  auto& content = found_content->second;
  FML_CHECK(content);
  transform->content = content;
}

void FakeFlatland::SetRootTransform(
    fuchsia::ui::composition::TransformId transform_id) {
  if (transform_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::SetRootTransform: TransformId 0 is invalid.";
    return;
  }

  auto found_new_root = pending_graph_.transform_map.find(transform_id.value);
  if (found_new_root == pending_graph_.transform_map.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::SetRootTransform: TransformId "
                     << transform_id.value << " does not exist.";
    return;
  }

  pending_graph_.root_transform = found_new_root->second;
}

void FakeFlatland::CreateViewport(
    fuchsia::ui::composition::ContentId viewport_id,
    fuchsia::ui::views::ViewportCreationToken token,
    fuchsia::ui::composition::ViewportProperties properties,
    fidl::InterfaceRequest<fuchsia::ui::composition::ChildViewWatcher>
        child_view_watcher) {
  if (viewport_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::CreateViewport: ContentId 0 is invalid.";
    return;
  }
  if (pending_graph_.content_map.count(viewport_id.value) != 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::CreateViewport: ContentId "
                     << viewport_id.value << " is already in use.";
    return;
  }

  auto viewport_token_koids = GetKoids(token.value);
  auto [emplaced_viewport, emplace_success] =
      pending_graph_.content_map.emplace(
          viewport_id.value,
          std::make_shared<FakeContent>(FakeViewport{
              .id = viewport_id,
              .viewport_properties = std::move(properties),
              .viewport_token = viewport_token_koids.first,
              .child_view_watcher = GetKoids(child_view_watcher).first,
          }));
  // TODO(fxb/85619): Raise a FlatlandError here
  FML_CHECK(emplace_success)
      << "FakeFlatland::CreateViewport: Internal error (content_map) adding "
         "viewport with id: "
      << viewport_id.value;

  auto [_, emplace_binding_success] = graph_bindings_.view_watchers.emplace(
      viewport_token_koids.first,
      ChildViewWatcher(std::move(token), std::move(child_view_watcher),
                       flatland_binding_.dispatcher()));
  // TODO(fxb/85619): Raise a FlatlandError here
  FML_CHECK(emplace_binding_success)
      << "FakeFlatland::CreateViewport: Internal error (view_watcher) adding "
         "viewport with id: "
      << viewport_id.value;
}

void FakeFlatland::CreateImage(
    fuchsia::ui::composition::ContentId image_id,
    fuchsia::ui::composition::BufferCollectionImportToken import_token,
    uint32_t vmo_index,
    fuchsia::ui::composition::ImageProperties properties) {
  if (image_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::CreateImage: ContentId 0 is invalid.";
    return;
  }
  if (pending_graph_.content_map.count(image_id.value) != 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::CreateImage: ContentId "
                     << image_id.value << " is already in use.";
    return;
  }

  auto import_token_koids = GetKoids(import_token);
  auto [emplaced_image, emplace_success] = pending_graph_.content_map.emplace(
      image_id.value, std::make_shared<FakeContent>(FakeImage{
                          .id = image_id,
                          .image_properties = std::move(properties),
                          .import_token = import_token_koids.first,
                          .vmo_index = vmo_index,
                      }));
  // TODO(fxb/85619): Raise a FlatlandError here
  FML_CHECK(emplace_success)
      << "FakeFlatland::CreateImage: Internal error (content_map) adding "
         "image with id: "
      << image_id.value;

  auto [_, emplace_binding_success] = graph_bindings_.images.emplace(
      import_token_koids.first, ImageBinding{
                                    .import_token = std::move(import_token),
                                });
  // TODO(fxb/85619): Raise a FlatlandError here
  FML_CHECK(emplace_binding_success)
      << "FakeFlatland::CreateImage: Internal error (images_binding) adding "
         "viewport with id: "
      << image_id.value;
}

void FakeFlatland::SetImageSampleRegion(
    fuchsia::ui::composition::ContentId image_id,
    fuchsia::math::RectF rect) {
  if (image_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::SetImageSampleRegion: ContentId 0 is invalid.";
    return;
  }

  auto found_content = pending_graph_.content_map.find(image_id.value);
  if (found_content == pending_graph_.content_map.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::SetImageSampleRegion: ContentId "
                     << image_id.value << " does not exist.";
    return;
  }

  auto& content = found_content->second;
  FML_CHECK(content);
  FakeImage* image = std::get_if<FakeImage>(content.get());
  if (image == nullptr) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::SetImageSampleRegion: ContentId "
                     << image_id.value << " is not an Image.";
    return;
  }

  image->sample_region = rect;
}

void FakeFlatland::SetImageDestinationSize(
    fuchsia::ui::composition::ContentId image_id,
    fuchsia::math::SizeU size) {
  if (image_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::SetImageDestinationSize: ContentId 0 is invalid.";
    return;
  }

  auto found_content = pending_graph_.content_map.find(image_id.value);
  if (found_content == pending_graph_.content_map.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::SetImageDestinationSize: ContentId "
                     << image_id.value << " does not exist.";
    return;
  }

  auto& content = found_content->second;
  FML_CHECK(content);
  FakeImage* image = std::get_if<FakeImage>(content.get());
  if (image == nullptr) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::SetImageDestinationSize: ContentId "
                     << image_id.value << " is not an Image.";
    return;
  }

  image->destination_size = size;
}

void FakeFlatland::SetImageBlendingFunction(
    fuchsia::ui::composition::ContentId image_id,
    fuchsia::ui::composition::BlendMode blend_mode) {
  if (image_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::SetImageDestinationSize: ContentId 0 is invalid.";
    return;
  }

  auto found_content = pending_graph_.content_map.find(image_id.value);
  if (found_content == pending_graph_.content_map.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::SetImageDestinationSize: ContentId "
                     << image_id.value << " does not exist.";
    return;
  }

  auto& content = found_content->second;
  FML_CHECK(content);
  FakeImage* image = std::get_if<FakeImage>(content.get());
  if (image == nullptr) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::SetImageDestinationSize: ContentId "
                     << image_id.value << " is not an Image.";
    return;
  }

  image->blend_mode = blend_mode;
}

void FakeFlatland::SetViewportProperties(
    fuchsia::ui::composition::ContentId viewport_id,
    fuchsia::ui::composition::ViewportProperties properties) {
  if (viewport_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::SetViewportProperties: ContentId 0 is invalid.";
    return;
  }

  auto found_content = pending_graph_.content_map.find(viewport_id.value);
  if (found_content == pending_graph_.content_map.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::SetViewportProperties: ContentId "
                     << viewport_id.value << " does not exist.";
    return;
  }

  auto& content = found_content->second;
  FML_CHECK(content);
  FakeViewport* viewport = std::get_if<FakeViewport>(content.get());
  if (viewport == nullptr) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::SetViewportProperties: ContentId "
                     << viewport_id.value << " is not a Viewport.";
    return;
  }

  viewport->viewport_properties = std::move(properties);
}

void FakeFlatland::ReleaseTransform(
    fuchsia::ui::composition::TransformId transform_id) {
  if (transform_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::ReleaseTransform: TransformId 0 is invalid.";
    return;
  }

  size_t erased = pending_graph_.transform_map.erase(transform_id.value);
  if (erased == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::ReleaseTransform: TransformId "
                     << transform_id.value << " does not exist.";
  }

  size_t parents_erased = parents_map_.erase(transform_id.value);
  if (parents_erased == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::ReleaseTransform: TransformId "
                     << transform_id.value << " does not exist in parents_map.";
  }
}

void FakeFlatland::ReleaseViewport(
    fuchsia::ui::composition::ContentId viewport_id,
    ReleaseViewportCallback callback) {
  if (viewport_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false)
        << "FakeFlatland::ReleaseViewport: ContentId 0 is invalid.";
    return;
  }

  auto found_content = pending_graph_.content_map.find(viewport_id.value);
  if (found_content == pending_graph_.content_map.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::ReleaseViewport: ContentId "
                     << viewport_id.value << " does not exist.";
    return;
  }

  auto& content = found_content->second;
  FML_CHECK(content);
  FakeViewport* viewport = std::get_if<FakeViewport>(content.get());
  if (viewport == nullptr) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::ReleaseViewport: ContentId "
                     << viewport_id.value << " is not a Viewport.";
    return;
  }

  pending_graph_.content_map.erase(found_content);
}

void FakeFlatland::ReleaseImage(fuchsia::ui::composition::ContentId image_id) {
  if (image_id.value == 0) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::ReleaseImage: ContentId 0 is invalid.";
    return;
  }

  auto found_content = pending_graph_.content_map.find(image_id.value);
  if (found_content == pending_graph_.content_map.end()) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::ReleaseImage: ContentId "
                     << image_id.value << " does not exist.";
    return;
  }

  auto& content = found_content->second;
  FML_CHECK(content);
  FakeImage* image = std::get_if<FakeImage>(content.get());
  if (image == nullptr) {
    // TODO(fxb/85619): Raise a FlatlandError here
    FML_CHECK(false) << "FakeFlatland::ReleaseImage: ContentId "
                     << image_id.value << " is not a Viewport.";
    return;
  }

  pending_graph_.content_map.erase(found_content);
}

void FakeFlatland::Clear() {
  parents_map_.clear();
  pending_graph_.Clear();
}

void FakeFlatland::SetDebugName(std::string debug_name) {
  debug_name_ = std::move(debug_name);
}

FakeFlatland::ParentViewportWatcher::ParentViewportWatcher(
    fuchsia::ui::views::ViewCreationToken view_token,
    fuchsia::ui::views::ViewIdentityOnCreation view_identity,
    fuchsia::ui::composition::ViewBoundProtocols view_protocols,
    fidl::InterfaceRequest<fuchsia::ui::composition::ParentViewportWatcher>
        parent_viewport_watcher,
    async_dispatcher_t* dispatcher)
    : view_token(std::move(view_token)),
      view_identity(std::move(view_identity)),
      view_protocols(std::move(view_protocols)),
      parent_viewport_watcher(this,
                              std::move(parent_viewport_watcher),
                              dispatcher) {}

FakeFlatland::ParentViewportWatcher::ParentViewportWatcher(
    ParentViewportWatcher&& other)
    : view_token(std::move(other.view_token)),
      view_identity(std::move(other.view_identity)),
      view_protocols(std::move(other.view_protocols)),
      parent_viewport_watcher(this,
                              other.parent_viewport_watcher.Unbind(),
                              other.parent_viewport_watcher.dispatcher()) {}

FakeFlatland::ParentViewportWatcher::~ParentViewportWatcher() = default;

void FakeFlatland::ParentViewportWatcher::NotImplemented_(
    const std::string& name) {
  FML_LOG(FATAL) << "FakeFlatland::ParentViewportWatcher does not implement "
                 << name;
}

void FakeFlatland::ParentViewportWatcher::GetLayout(
    GetLayoutCallback callback) {
  NotImplemented_("GetLayout");
}

void FakeFlatland::ParentViewportWatcher::GetStatus(
    GetStatusCallback callback) {
  NotImplemented_("GetStatus");
}

FakeFlatland::ChildViewWatcher::ChildViewWatcher(
    fuchsia::ui::views::ViewportCreationToken viewport_token,
    fidl::InterfaceRequest<fuchsia::ui::composition::ChildViewWatcher>
        child_view_watcher,
    async_dispatcher_t* dispatcher)
    : viewport_token(std::move(viewport_token)),
      child_view_watcher(this, std::move(child_view_watcher), dispatcher) {}

FakeFlatland::ChildViewWatcher::ChildViewWatcher(ChildViewWatcher&& other)
    : viewport_token(std::move(other.viewport_token)),
      child_view_watcher(this,
                         other.child_view_watcher.Unbind(),
                         other.child_view_watcher.dispatcher()) {}

FakeFlatland::ChildViewWatcher::~ChildViewWatcher() = default;

void FakeFlatland::ChildViewWatcher::NotImplemented_(const std::string& name) {
  FML_LOG(FATAL) << "FakeFlatland::ChildViewWatcher does not implement "
                 << name;
}

void FakeFlatland::ChildViewWatcher::GetStatus(GetStatusCallback callback) {
  NotImplemented_("GetStatus");
}

}  // namespace flutter_runner::testing
