// 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),
                       }));
  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;
}

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
