// Copyright 2020 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 <fuchsia/scenic/scheduling/cpp/fidl.h>
#include <fuchsia/ui/policy/cpp/fidl.h>
#include <fuchsia/ui/scenic/cpp/fidl.h>
#include <lib/async-loop/default.h>
#include <lib/sys/cpp/component_context.h>

#include "assets/directory_asset_bundle.h"
#include "flutter/common/graphics/persistent_cache.h"
#include "flutter/fml/memory/ref_ptr.h"
#include "flutter/fml/message_loop_impl.h"
#include "flutter/fml/task_runner.h"
#include "flutter/shell/common/serialization_callbacks.h"
#include "flutter/shell/platform/fuchsia/flutter/logging.h"
#include "flutter/shell/platform/fuchsia/flutter/runner.h"
#include "flutter/shell/platform/fuchsia/flutter/session_connection.h"
#include "gtest/gtest.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkSerialProcs.h"

using namespace flutter_runner;
using namespace flutter;

namespace flutter_runner {
namespace testing {

class MockTaskRunner : public fml::BasicTaskRunner {
 public:
  MockTaskRunner() {}
  virtual ~MockTaskRunner() {}

  void PostTask(const fml::closure& task) override {
    outstanding_tasks_.push(task);
  }

  int GetTaskCount() { return task_count_; }

  void Run() {
    while (!outstanding_tasks_.empty()) {
      outstanding_tasks_.front()();
      outstanding_tasks_.pop();
      task_count_++;
    }
  }

 private:
  int task_count_ = 0;
  std::queue<const fml::closure> outstanding_tasks_;
};

class EngineTest : public ::testing::Test {
 public:
  void WarmupSkps() {
    // Have to create a message loop so default async dispatcher gets set,
    // otherwise we segfault creating the VulkanSurfaceProducer
    auto loop = fml::MessageLoopImpl::Create();

    context_ = sys::ComponentContext::CreateAndServeOutgoingDirectory();
    scenic_ = context_->svc()->Connect<fuchsia::ui::scenic::Scenic>();
    scenic::Session session(scenic_.get());
    surface_producer_ = std::make_unique<VulkanSurfaceProducer>(&session);

    Engine::WarmupSkps(&concurrent_task_runner_, &raster_task_runner_,
                       *surface_producer_);
  }

 protected:
  MockTaskRunner concurrent_task_runner_;
  MockTaskRunner raster_task_runner_;
  std::unique_ptr<VulkanSurfaceProducer> surface_producer_;

  std::unique_ptr<sys::ComponentContext> context_;
  fuchsia::ui::scenic::ScenicPtr scenic_;
};

TEST_F(EngineTest, SkpWarmup) {
  SkISize draw_size = SkISize::Make(100, 100);
  SkPictureRecorder recorder;
  auto canvas = recorder.beginRecording(draw_size.width(), draw_size.height());

  // adapted from https://fiddle.skia.org/c/@Canvas_drawLine
  SkPaint paint;
  paint.setColor(0xFF9a67be);
  paint.setStrokeWidth(20);
  canvas->drawLine(0, 0, draw_size.width(), draw_size.height(), paint);
  canvas->drawLine(0, draw_size.height(), draw_size.width(), 0, paint);

  sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
  SkSerialProcs procs = {0};
  procs.fImageProc = SerializeImageWithoutData;
  procs.fTypefaceProc = SerializeTypefaceWithoutData;
  sk_sp<SkData> data = picture->serialize(&procs);
  ASSERT_TRUE(data);
  ASSERT_GT(data->size(), 0u);

  fml::NonOwnedMapping mapping(data->bytes(), data->size());

  fml::ScopedTemporaryDirectory asset_dir;
  fml::UniqueFD asset_dir_fd = fml::OpenDirectory(
      asset_dir.path().c_str(), false, fml::FilePermission::kRead);
  fml::UniqueFD subdir_fd = fml::OpenDirectory(asset_dir_fd, "shaders", true,
                                               fml::FilePermission::kReadWrite);

  bool success = fml::WriteAtomically(subdir_fd, "test.skp", mapping);
  ASSERT_TRUE(success);

  auto asset_manager = std::make_shared<AssetManager>();
  asset_manager->PushBack(
      std::make_unique<DirectoryAssetBundle>(std::move(asset_dir_fd), false));

  PersistentCache::GetCacheForProcess()->SetAssetManager(asset_manager);

  WarmupSkps();
  concurrent_task_runner_.Run();
  raster_task_runner_.Run();

  EXPECT_EQ(concurrent_task_runner_.GetTaskCount(), 1);
  EXPECT_EQ(raster_task_runner_.GetTaskCount(), 1);
}

}  // namespace testing
}  // namespace flutter_runner
