// 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 "flutter/shell/platform/embedder/tests/embedder_test_compositor.h"

#include "flutter/fml/logging.h"
#include "flutter/shell/platform/embedder/tests/embedder_assertions.h"
#include "third_party/skia/include/core/SkSurface.h"

namespace flutter {
namespace testing {

EmbedderTestCompositor::EmbedderTestCompositor(SkISize surface_size,
                                               sk_sp<GrDirectContext> context)
    : surface_size_(surface_size), context_(context) {
  FML_CHECK(!surface_size_.isEmpty()) << "Surface size must not be empty";
}

EmbedderTestCompositor::~EmbedderTestCompositor() = default;

static void InvokeAllCallbacks(const std::vector<fml::closure>& callbacks) {
  for (const auto& callback : callbacks) {
    if (callback) {
      callback();
    }
  }
}

bool EmbedderTestCompositor::CreateBackingStore(
    const FlutterBackingStoreConfig* config,
    FlutterBackingStore* backing_store_out) {
  bool success = backingstore_producer_->Create(config, backing_store_out);
  if (success) {
    backing_stores_created_++;
    InvokeAllCallbacks(on_create_render_target_callbacks_);
  }
  return success;
}

bool EmbedderTestCompositor::CollectBackingStore(
    const FlutterBackingStore* backing_store) {
  // We have already set the destruction callback for the various backing
  // stores. Our user_data is just the canvas from that backing store and does
  // not need to be explicitly collected. Embedders might have some other state
  // they want to collect though.
  backing_stores_collected_++;
  InvokeAllCallbacks(on_collect_render_target_callbacks_);
  return true;
}

void EmbedderTestCompositor::SetBackingStoreProducer(
    std::unique_ptr<EmbedderTestBackingStoreProducer> backingstore_producer) {
  backingstore_producer_ = std::move(backingstore_producer);
}

sk_sp<SkImage> EmbedderTestCompositor::GetLastComposition() {
  return last_composition_;
}

bool EmbedderTestCompositor::Present(const FlutterLayer** layers,
                                     size_t layers_count) {
  if (!UpdateOffscrenComposition(layers, layers_count)) {
    FML_LOG(ERROR)
        << "Could not update the off-screen composition in the test compositor";
    return false;
  }

  // If the test has asked to access the layers and renderers being presented.
  // Access the same and present it to the test for its test assertions.
  if (present_callback_) {
    auto callback = present_callback_;
    if (present_callback_is_one_shot_) {
      present_callback_ = nullptr;
    }
    callback(layers, layers_count);
  }

  InvokeAllCallbacks(on_present_callbacks_);
  return true;
}

void EmbedderTestCompositor::SetNextPresentCallback(
    const PresentCallback& next_present_callback) {
  SetPresentCallback(next_present_callback, true);
}

void EmbedderTestCompositor::SetPresentCallback(
    const PresentCallback& present_callback,
    bool one_shot) {
  FML_CHECK(!present_callback_);
  present_callback_ = present_callback;
  present_callback_is_one_shot_ = one_shot;
}

void EmbedderTestCompositor::SetNextSceneCallback(
    const NextSceneCallback& next_scene_callback) {
  FML_CHECK(!next_scene_callback_);
  next_scene_callback_ = next_scene_callback;
}

void EmbedderTestCompositor::SetPlatformViewRendererCallback(
    const PlatformViewRendererCallback& callback) {
  platform_view_renderer_callback_ = callback;
}

size_t EmbedderTestCompositor::GetPendingBackingStoresCount() const {
  FML_CHECK(backing_stores_created_ >= backing_stores_collected_);
  return backing_stores_created_ - backing_stores_collected_;
}

size_t EmbedderTestCompositor::GetBackingStoresCreatedCount() const {
  return backing_stores_created_;
}

size_t EmbedderTestCompositor::GetBackingStoresCollectedCount() const {
  return backing_stores_collected_;
}

void EmbedderTestCompositor::AddOnCreateRenderTargetCallback(
    fml::closure callback) {
  on_create_render_target_callbacks_.push_back(callback);
}

void EmbedderTestCompositor::AddOnCollectRenderTargetCallback(
    fml::closure callback) {
  on_collect_render_target_callbacks_.push_back(callback);
}

void EmbedderTestCompositor::AddOnPresentCallback(fml::closure callback) {
  on_present_callbacks_.push_back(callback);
}

sk_sp<GrDirectContext> EmbedderTestCompositor::GetGrContext() {
  return context_;
}

}  // namespace testing
}  // namespace flutter
