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

#include <lib/fidl/cpp/clone.h>
#include <lib/zx/channel.h>
#include <lib/zx/eventpair.h>

#include "flutter/fml/logging.h"

namespace flutter_runner::testing {
namespace {

using FakeTransformCache =
    std::unordered_map<const FakeTransform*, std::shared_ptr<FakeTransform>>;

std::vector<std::shared_ptr<FakeTransform>> CloneFakeTransformVector(
    const std::vector<std::shared_ptr<FakeTransform>>& transforms,
    FakeTransformCache& transform_cache);

std::shared_ptr<FakeContent> CloneFakeContent(
    const std::shared_ptr<FakeContent>& content) {
  if (content == nullptr) {
    return nullptr;
  }

  if (FakeViewport* viewport = std::get_if<FakeViewport>(content.get())) {
    return std::make_shared<FakeContent>(FakeViewport{
        .id = viewport->id,
        .viewport_properties = fidl::Clone(viewport->viewport_properties),
        .viewport_token = viewport->viewport_token,
        .child_view_watcher = viewport->child_view_watcher,
    });
  } else if (FakeImage* image = std::get_if<FakeImage>(content.get())) {
    return std::make_shared<FakeContent>(FakeImage{
        .id = image->id,
        .image_properties = fidl::Clone(image->image_properties),
        .sample_region = image->sample_region,
        .destination_size = image->destination_size,
        .opacity = image->opacity,
        .blend_mode = image->blend_mode,
        .import_token = image->import_token,
        .vmo_index = image->vmo_index,
    });
  } else {
    FML_UNREACHABLE();
  }
}

std::shared_ptr<FakeTransform> CloneFakeTransform(
    const std::shared_ptr<FakeTransform>& transform,
    FakeTransformCache& transform_cache) {
  if (transform == nullptr) {
    return nullptr;
  }

  auto found_transform = transform_cache.find(transform.get());
  if (found_transform != transform_cache.end()) {
    return found_transform->second;
  }

  auto [emplaced_transform, success] = transform_cache.emplace(
      transform.get(), std::make_shared<FakeTransform>(FakeTransform{
                           .id = transform->id,
                           .translation = transform->translation,
                           .clip_bounds = transform->clip_bounds,
                           .orientation = transform->orientation,
                           .children = CloneFakeTransformVector(
                               transform->children, transform_cache),
                           .content = CloneFakeContent(transform->content),
                           .num_hit_regions = transform->num_hit_regions,
                       }));
  FML_CHECK(success);

  return emplaced_transform->second;
}

std::vector<std::shared_ptr<FakeTransform>> CloneFakeTransformVector(
    const std::vector<std::shared_ptr<FakeTransform>>& transforms,
    FakeTransformCache& transform_cache) {
  std::vector<std::shared_ptr<FakeTransform>> clones;
  for (auto& transform : transforms) {
    clones.emplace_back(CloneFakeTransform(transform, transform_cache));
  }
  return clones;
}

}  // namespace

ViewTokenPair ViewTokenPair::New() {
  ViewTokenPair token_pair;
  auto status = zx::channel::create(0u, &token_pair.view_token.value,
                                    &token_pair.viewport_token.value);
  FML_CHECK(status == ZX_OK);

  return token_pair;
}

BufferCollectionTokenPair BufferCollectionTokenPair::New() {
  BufferCollectionTokenPair token_pair;
  auto status = zx::eventpair::create(0u, &token_pair.export_token.value,
                                      &token_pair.import_token.value);
  FML_CHECK(status == ZX_OK);

  return token_pair;
}

bool FakeView::operator==(const FakeView& other) const {
  return view_token == other.view_token && view_ref == other.view_ref &&
         view_ref_control == other.view_ref_control &&
         view_ref_focused == other.view_ref_focused &&
         focuser == other.focuser && touch_source == other.touch_source &&
         mouse_source == other.mouse_source &&
         parent_viewport_watcher == other.parent_viewport_watcher;
}

bool FakeViewport::operator==(const FakeViewport& other) const {
  return id == other.id && viewport_properties == other.viewport_properties &&
         viewport_token == other.viewport_token &&
         child_view_watcher == other.child_view_watcher;
}

bool FakeImage::operator==(const FakeImage& other) const {
  return id == other.id && image_properties == other.image_properties &&
         sample_region == other.sample_region &&
         destination_size == other.destination_size &&
         opacity == other.opacity && blend_mode == other.blend_mode &&
         import_token == other.import_token && vmo_index == other.vmo_index;
}

bool FakeTransform::operator==(const FakeTransform& other) const {
  return id == other.id && translation == other.translation &&
         *clip_bounds == *other.clip_bounds &&
         orientation == other.orientation && children == other.children &&
         content == other.content && num_hit_regions == other.num_hit_regions;
}

bool FakeGraph::operator==(const FakeGraph& other) const {
  return transform_map == other.transform_map &&
         content_map == other.content_map &&
         root_transform == other.root_transform && view == other.view;
}

void FakeGraph::Clear() {
  view.reset();
  root_transform.reset();
  transform_map.clear();
  content_map.clear();
}

FakeGraph FakeGraph::Clone() const {
  FakeGraph clone;
  FakeTransformCache transform_cache;

  for (const auto& [transform_id, transform] : transform_map) {
    FML_CHECK(transform);
    clone.transform_map.emplace(transform_id,
                                CloneFakeTransform(transform, transform_cache));
  }
  for (const auto& [content_id, content] : content_map) {
    FML_CHECK(content);
    clone.content_map.emplace(content_id, CloneFakeContent(content));
  }
  if (root_transform) {
    auto found_transform = transform_cache.find(root_transform.get());
    FML_CHECK(found_transform != transform_cache.end());
    clone.root_transform = found_transform->second;
  }
  if (view.has_value()) {
    clone.view.emplace(view.value());
  }

  return clone;
}

}  // namespace flutter_runner::testing
