// Copyright 2020 The Fuchsia 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 "src/ui/scenic/lib/flatland/engine/engine.h"

#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async-testing/test_loop.h>
#include <lib/async/cpp/wait.h>
#include <lib/async/default.h>
#include <lib/fdio/directory.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/eventpair.h>

#include <limits>
#include <thread>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "src/lib/fsl/handles/object_info.h"
#include "src/lib/testing/loop_fixture/real_loop_fixture.h"
#include "src/ui/scenic/lib/display/tests/mock_display_controller.h"
#include "src/ui/scenic/lib/flatland/engine/tests/mock_display_controller.h"
#include "src/ui/scenic/lib/flatland/flatland.h"
#include "src/ui/scenic/lib/flatland/global_image_data.h"
#include "src/ui/scenic/lib/flatland/global_matrix_data.h"
#include "src/ui/scenic/lib/flatland/global_topology_data.h"
#include "src/ui/scenic/lib/flatland/renderer/null_renderer.h"
#include "src/ui/scenic/lib/flatland/renderer/renderer.h"
#include "src/ui/scenic/lib/scheduling/frame_scheduler.h"
#include "src/ui/scenic/lib/scheduling/id.h"

#include <glm/gtx/matrix_transform_2d.hpp>

using ::testing::_;
using ::testing::Return;

using flatland::ImageMetadata;
using flatland::LinkSystem;
using flatland::MockDisplayController;
using flatland::Renderer;
using flatland::TransformGraph;
using flatland::TransformHandle;
using flatland::UberStruct;
using flatland::UberStructSystem;
using fuchsia::ui::scenic::internal::ContentLink;
using fuchsia::ui::scenic::internal::ContentLinkStatus;
using fuchsia::ui::scenic::internal::ContentLinkToken;
using fuchsia::ui::scenic::internal::GraphLink;
using fuchsia::ui::scenic::internal::GraphLinkToken;
using fuchsia::ui::scenic::internal::LayoutInfo;
using fuchsia::ui::scenic::internal::LinkProperties;

namespace {

class EngineTest : public gtest::RealLoopFixture {
 public:
  EngineTest()
      : uber_struct_system_(std::make_shared<UberStructSystem>()),
        link_system_(std::make_shared<LinkSystem>(uber_struct_system_->GetNextInstanceId())) {}

  void SetUp() override {
    gtest::RealLoopFixture::SetUp();

    // Create the SysmemAllocator.
    zx_status_t status = fdio_service_connect(
        "/svc/fuchsia.sysmem.Allocator", sysmem_allocator_.NewRequest().TakeChannel().release());

    async_set_default_dispatcher(dispatcher());

    renderer_ = std::make_shared<flatland::NullRenderer>();

    zx::channel device_channel_server;
    zx::channel device_channel_client;
    FX_CHECK(ZX_OK == zx::channel::create(0, &device_channel_server, &device_channel_client));
    zx::channel controller_channel_server;
    zx::channel controller_channel_client;
    FX_CHECK(ZX_OK ==
             zx::channel::create(0, &controller_channel_server, &controller_channel_client));

    mock_display_controller_ = std::make_unique<flatland::MockDisplayController>();
    mock_display_controller_->Bind(std::move(device_channel_server),
                                   std::move(controller_channel_server));

    auto unique_display_controller =
        std::make_unique<fuchsia::hardware::display::ControllerSyncPtr>();
    unique_display_controller->Bind(std::move(controller_channel_client));

    engine_ = std::make_unique<flatland::Engine>(std::move(unique_display_controller), renderer_,
                                                 link_system_, uber_struct_system_);
  }

  void TearDown() override {
    sysmem_allocator_ = nullptr;
    renderer_.reset();
    engine_.reset();
    mock_display_controller_.reset();

    // Move the channel to a local variable which will go out of scope
    // and close when this function returns.
    auto local = local_.release();

    gtest::RealLoopFixture::TearDown();
  }

  fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken> CreateToken() {
    zx::channel remote;
    zx::channel::create(0, &local_, &remote);
    fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken> token{std::move(remote)};
    return token;
  }

  class FakeFlatlandSession {
   public:
    FakeFlatlandSession(const std::shared_ptr<UberStructSystem>& uber_struct_system,
                        const std::shared_ptr<LinkSystem>& link_system, EngineTest* harness)
        : uber_struct_system_(uber_struct_system),
          link_system_(link_system),
          harness_(harness),
          id_(uber_struct_system_->GetNextInstanceId()),
          graph_(id_),
          queue_(uber_struct_system_->AllocateQueueForSession(id_)) {}

    // Use the TransformGraph API to create and manage transforms and their children.
    TransformGraph& graph() { return graph_; }

    // Returns the link_origin for this session.
    TransformHandle GetLinkOrigin() {
      EXPECT_TRUE(parent_link_.has_value());
      return parent_link_.value().parent_link.link_origin;
    }

    // Clears the ParentLink for this session, if one exists.
    void ClearParentLink() { parent_link_.reset(); }

    // Holds the ContentLink and LinkSystem::ChildLink objects since if they fall out of scope,
    // the LinkSystem will delete the link. Tests should add |child_link.link_handle| to their
    // TransformGraphs to use the ChildLink in a topology.
    struct ChildLink {
      fidl::InterfacePtr<ContentLink> content_link;
      LinkSystem::ChildLink child_link;

      // Returns the handle the parent should add as a child in its local topology to include the
      // link in the topology.
      TransformHandle GetLinkHandle() const { return child_link.link_handle; }
    };

    // Links this session to |parent_session| and returns the ChildLink, which should be used with
    // the parent session. If the return value drops out of scope, tests should call
    // ClearParentLink() on this session.
    ChildLink LinkToParent(FakeFlatlandSession& parent_session) {
      // Create the tokens.
      ContentLinkToken parent_token;
      GraphLinkToken child_token;
      EXPECT_EQ(zx::eventpair::create(0, &parent_token.value, &child_token.value), ZX_OK);

      // Create the parent link.
      fidl::InterfacePtr<GraphLink> graph_link;
      LinkSystem::ParentLink parent_link = link_system_->CreateParentLink(
          std::move(child_token), graph_link.NewRequest(), graph_.CreateTransform());

      // Create the child link.
      fidl::InterfacePtr<ContentLink> content_link;
      LinkSystem::ChildLink child_link = link_system_->CreateChildLink(
          std::move(parent_token), LinkProperties(), content_link.NewRequest(),
          parent_session.graph_.CreateTransform());

      // Run the loop to establish the link.
      harness_->RunLoopUntilIdle();

      parent_link_ = ParentLink({
          .graph_link = std::move(graph_link),
          .parent_link = std::move(parent_link),
      });

      return ChildLink({
          .content_link = std::move(content_link),
          .child_link = std::move(child_link),
      });
    }

    // Allocates a new UberStruct with a local_topology rooted at |local_root|. If this session has
    // a ParentLink, the link_origin of that ParentLink will be used instead.
    std::unique_ptr<UberStruct> CreateUberStructWithCurrentTopology(TransformHandle local_root) {
      auto uber_struct = std::make_unique<UberStruct>();

      // Only use the supplied |local_root| if no there is no ParentLink, otherwise use the
      // |link_origin| from the ParentLink.
      const TransformHandle root =
          parent_link_.has_value() ? parent_link_.value().parent_link.link_origin : local_root;

      // Compute the local topology and place it in the UberStruct.
      auto local_topology_data =
          graph_.ComputeAndCleanup(root, std::numeric_limits<uint64_t>::max());
      EXPECT_NE(local_topology_data.iterations, std::numeric_limits<uint64_t>::max());
      EXPECT_TRUE(local_topology_data.cyclical_edges.empty());

      uber_struct->local_topology = local_topology_data.sorted_transforms;

      return uber_struct;
    }

    // Pushes |uber_struct| to the UberStructSystem and updates the system so that it represents
    // this session in the InstanceMap.
    void PushUberStruct(std::unique_ptr<UberStruct> uber_struct) {
      EXPECT_FALSE(uber_struct->local_topology.empty());
      EXPECT_EQ(uber_struct->local_topology[0].handle.GetInstanceId(), id_);

      queue_->Push(/*present_id=*/0, std::move(uber_struct));
      uber_struct_system_->UpdateSessions({{id_, 0}});
    }

   private:
    // Shared systems for all sessions.
    std::shared_ptr<UberStructSystem> uber_struct_system_;
    std::shared_ptr<LinkSystem> link_system_;

    // The test harness to give access to RunLoopUntilIdle().
    EngineTest* harness_;

    // Data specific this session.
    scheduling::SessionId id_;
    TransformGraph graph_;
    std::shared_ptr<UberStructSystem::UberStructQueue> queue_;

    // Holds the GraphLink and LinkSystem::ParentLink objects since if they fall out of scope,
    // the LinkSystem will delete the link. When |parent_link_| has a value, the
    // |parent_link.link_origin| from this object is used as the root TransformHandle.
    struct ParentLink {
      fidl::InterfacePtr<GraphLink> graph_link;
      LinkSystem::ParentLink parent_link;
    };
    std::optional<ParentLink> parent_link_;
  };

  FakeFlatlandSession CreateSession() {
    return FakeFlatlandSession(uber_struct_system_, link_system_, this);
  }

 protected:
  // Systems that are populated with data from Flatland instances.
  const std::shared_ptr<UberStructSystem> uber_struct_system_;
  const std::shared_ptr<LinkSystem> link_system_;
  std::shared_ptr<flatland::NullRenderer> renderer_;
  fuchsia::sysmem::AllocatorSyncPtr sysmem_allocator_;
  std::unique_ptr<flatland::Engine> engine_;
  std::unique_ptr<flatland::MockDisplayController> mock_display_controller_;

 private:
  zx::channel local_;
};

}  // namespace

namespace flatland {
namespace test {

TEST_F(EngineTest, ImportAndReleaseBufferCollectionTest) {
  auto mock = mock_display_controller_.get();
  // Set the mock display controller functions and wait for messages.
  std::thread server([&mock]() mutable {
    // Wait once for call to ImportBufferCollection, once for setting the
    // constraints, and once for call to ReleaseBufferCollection
    for (uint32_t i = 0; i < 3; i++) {
      mock->WaitForMessage();
    }
  });

  const sysmem_util::GlobalBufferCollectionId kGlobalBufferCollectionId = 15;

  EXPECT_CALL(*mock_display_controller_.get(),
              ImportBufferCollection(kGlobalBufferCollectionId, _, _))
      .WillOnce(testing::Invoke(
          [](uint64_t, fidl::InterfaceHandle<class ::fuchsia::sysmem::BufferCollectionToken>,
             MockDisplayController::ImportBufferCollectionCallback callback) { callback(ZX_OK); }));
  EXPECT_CALL(*mock_display_controller_.get(),
              SetBufferCollectionConstraints(kGlobalBufferCollectionId, _, _))
      .WillOnce(testing::Invoke(
          [](uint64_t collection_id, fuchsia::hardware::display::ImageConfig config,
             MockDisplayController::SetBufferCollectionConstraintsCallback callback) {
            callback(ZX_OK);
          }));
  engine_->ImportBufferCollection(kGlobalBufferCollectionId, nullptr, CreateToken());

  EXPECT_CALL(*mock_display_controller_, ReleaseBufferCollection(kGlobalBufferCollectionId))
      .WillOnce(Return());
  engine_->ReleaseBufferCollection(kGlobalBufferCollectionId);

  server.join();
}

TEST_F(EngineTest, ImportImageErrorCases) {
  const sysmem_util::GlobalBufferCollectionId kGlobalBufferCollectionId = 30;
  const flatland::GlobalImageId kImageId = 50;
  const uint32_t kVmoCount = 2;
  const uint32_t kVmoIdx = 1;
  const uint32_t kMaxWidth = 100;
  const uint32_t kMaxHeight = 200;
  uint32_t num_times_import_image_called = 0;

  EXPECT_CALL(*mock_display_controller_.get(),
              ImportBufferCollection(kGlobalBufferCollectionId, _, _))
      .WillOnce(testing::Invoke(
          [](uint64_t, fidl::InterfaceHandle<class ::fuchsia::sysmem::BufferCollectionToken>,
             MockDisplayController::ImportBufferCollectionCallback callback) { callback(ZX_OK); }));

  EXPECT_CALL(*mock_display_controller_.get(),
              SetBufferCollectionConstraints(kGlobalBufferCollectionId, _, _))
      .WillOnce(testing::Invoke(
          [](uint64_t collection_id, fuchsia::hardware::display::ImageConfig config,
             MockDisplayController::SetBufferCollectionConstraintsCallback callback) {
            callback(ZX_OK);
          }));

  // Set the mock display controller functions and wait for messages.
  auto mock = mock_display_controller_.get();
  std::thread server([&mock]() mutable {
    // Wait once for call to ImportBufferCollection, once for setting
    // the buffer collection constraints, a single valid call to
    // ImportImage() 1 invalid call to ImportImage(), and a single
    // call to ReleaseImage(). Although there are more than three
    // invalid calls to ImportImage() below, only 3 of them make it
    // all the way to the display controller, which is why we only
    // have to wait 3 times.
    for (uint32_t i = 0; i < 5; i++) {
      mock->WaitForMessage();
    }
  });

  engine_->ImportBufferCollection(kGlobalBufferCollectionId, nullptr, CreateToken());

  ImageMetadata metadata = {
      .collection_id = kGlobalBufferCollectionId,
      .identifier = kImageId,
      .vmo_idx = kVmoIdx,
      .width = 20,
      .height = 30,
  };

  // Make sure that the engine returns true if the display controller returns true.
  const uint64_t kDisplayImageId = 70;
  EXPECT_CALL(*mock_display_controller_.get(),
              ImportImage(_, kGlobalBufferCollectionId, kVmoIdx, _))
      .WillOnce(testing::Invoke([](fuchsia::hardware::display::ImageConfig image_config,
                                   uint64_t collection_id, uint32_t index,
                                   MockDisplayController::ImportImageCallback callback) {
        callback(ZX_OK, /*display_image_id*/ kDisplayImageId);
      }));
  auto result = engine_->ImportImage(metadata);
  EXPECT_TRUE(result);

  // Make sure we can release the image properly.
  EXPECT_CALL(*mock_display_controller_, ReleaseImage(kDisplayImageId)).WillOnce(Return());
  engine_->ReleaseImage(metadata.identifier);

  // Make sure that the engine returns false if the display controller returns an error
  EXPECT_CALL(*mock_display_controller_.get(),
              ImportImage(_, kGlobalBufferCollectionId, kVmoIdx, _))
      .WillOnce(testing::Invoke([](fuchsia::hardware::display::ImageConfig image_config,
                                   uint64_t collection_id, uint32_t index,
                                   MockDisplayController::ImportImageCallback callback) {
        callback(ZX_ERR_INVALID_ARGS, /*display_image_id*/ 0);
      }));
  result = engine_->ImportImage(metadata);
  EXPECT_FALSE(result);

  // Collection ID can't be invalid. This shouldn't reach the display controller.
  EXPECT_CALL(*mock_display_controller_.get(),
              ImportImage(_, kGlobalBufferCollectionId, kVmoIdx, _))
      .Times(0);
  auto copy_metadata = metadata;
  copy_metadata.collection_id = sysmem_util::kInvalidId;
  result = engine_->ImportImage(copy_metadata);
  EXPECT_FALSE(result);

  // Image Id can't be 0. This shouldn't reach the display controller.
  EXPECT_CALL(*mock_display_controller_.get(),
              ImportImage(_, kGlobalBufferCollectionId, kVmoIdx, _))
      .Times(0);
  copy_metadata = metadata;
  copy_metadata.identifier = 0;
  result = engine_->ImportImage(copy_metadata);
  EXPECT_FALSE(result);

  // Width can't be 0. This shouldn't reach the display controller.
  EXPECT_CALL(*mock_display_controller_.get(),
              ImportImage(_, kGlobalBufferCollectionId, kVmoIdx, _))
      .Times(0);
  copy_metadata = metadata;
  copy_metadata.width = 0;
  result = engine_->ImportImage(copy_metadata);
  EXPECT_FALSE(result);

  // Height can't be 0. This shouldn't reach the display controller.
  EXPECT_CALL(*mock_display_controller_.get(), ImportImage(_, _, 0, _)).Times(0);
  copy_metadata = metadata;
  copy_metadata.height = 0;
  result = engine_->ImportImage(copy_metadata);
  EXPECT_FALSE(result);

  server.join();
}

// When compositing directly to a hardware display layer, the display controller
// takes in source and destination Frame object types, which mirrors flatland usage.
// The source frames are nonnormalized UV coordinates and the destination frames are
// screenspace coordinates given in pixels. So this test makes sure that the rectangle
// and frame data that is generated by flatland sends along to the display controller
// the proper source and destination frame data. Each source and destination frame pair
// should be added to its own layer on the display.
TEST_F(EngineTest, HardwareFrameCorrectnessTest) {
  // Create a parent and child session.
  auto parent_session = CreateSession();
  auto child_session = CreateSession();

  // Create a link between the two.
  auto child_link = child_session.LinkToParent(parent_session);

  // Create the root handle for the parent and a handle that will have an image attached.
  const TransformHandle parent_root_handle = parent_session.graph().CreateTransform();
  const TransformHandle parent_image_handle = parent_session.graph().CreateTransform();

  // Add the two children to the parent root: link, then image.
  parent_session.graph().AddChild(parent_root_handle, child_link.GetLinkHandle());
  parent_session.graph().AddChild(parent_root_handle, parent_image_handle);

  // Create an image handle for the child.
  const TransformHandle child_image_handle = child_session.graph().CreateTransform();

  // Attach that image handle to the link_origin.
  child_session.graph().AddChild(child_session.GetLinkOrigin(), child_image_handle);

  // Get an UberStruct for the parent session.
  auto parent_struct = parent_session.CreateUberStructWithCurrentTopology(parent_root_handle);

  // Add an image.
  parent_struct->images[parent_image_handle] = ImageMetadata({
      .vmo_idx = 1,
      .width = 128,
      .height = 256,
  });

  parent_struct->local_matrices[parent_image_handle] = glm::mat3(1);
  parent_struct->local_matrices[parent_image_handle] =
      glm::scale(glm::translate(glm::mat3(1.0), glm::vec2(9, 13)), glm::vec2(10, 20));

  // Submit the UberStruct.
  parent_session.PushUberStruct(std::move(parent_struct));

  // Get an UberStruct for the child session. Note that the argument will be ignored anyway.
  auto child_struct =
      child_session.CreateUberStructWithCurrentTopology(child_session.GetLinkOrigin());

  // Add an image.
  child_struct->images[child_image_handle] = ImageMetadata({
      .vmo_idx = 2,
      .width = 512,
      .height = 1024,
  });
  child_struct->local_matrices[child_image_handle] =
      glm::scale(glm::translate(glm::mat3(1), glm::vec2(5, 7)), glm::vec2(30, 40));

  // Submit the UberStruct.
  child_session.PushUberStruct(std::move(child_struct));

  uint64_t display_id = 1;
  glm::uvec2 resolution(1024, 768);

  // We will end up with 2 source frames, 2 destination frames, and two layers beind sent to the
  // display.
  fuchsia::hardware::display::Frame sources[2] = {
      {.x_pos = 0u, .y_pos = 0u, .width = 512, .height = 1024u},
      {.x_pos = 0u, .y_pos = 0u, .width = 128u, .height = 256u}};

  fuchsia::hardware::display::Frame destinations[2] = {
      {.x_pos = 5u, .y_pos = 7u, .width = 30, .height = 40u},
      {.x_pos = 9u, .y_pos = 13u, .width = 10u, .height = 20u}};

  // Setup the EXPECT_CALLs for gmock.
  uint64_t layer_id = 1;
  EXPECT_CALL(*mock_display_controller_.get(), CreateLayer(_))
      .WillRepeatedly(testing::Invoke([&](MockDisplayController::CreateLayerCallback callback) {
        callback(ZX_OK, layer_id++);
      }));

  std::vector<uint64_t> layers = {1u, 2u};
  EXPECT_CALL(*mock_display_controller_.get(), SetDisplayLayers(display_id, layers)).Times(1);

  // Unfortunately, |fuchsia::hardware::display::Frame| doesn't have an equality operator, so
  // we can't just pass in the values we're expecting into the function as parameters. We can
  // still use fidl::Equals inside the function body, however.
  EXPECT_CALL(*mock_display_controller_.get(), SetLayerPrimaryPosition(layers[0], _, _, _))
      .WillOnce(
          testing::Invoke([&](uint64_t layer_id, fuchsia::hardware::display::Transform transform,
                              fuchsia::hardware::display::Frame src_frame,
                              fuchsia::hardware::display::Frame dest_frame) {
            EXPECT_TRUE(fidl::Equals(src_frame, sources[0]));
            EXPECT_TRUE(fidl::Equals(dest_frame, destinations[0]));
          }));

  EXPECT_CALL(*mock_display_controller_.get(), SetLayerPrimaryPosition(layers[1], _, _, _))
      .WillOnce(
          testing::Invoke([&](uint64_t layer_id, fuchsia::hardware::display::Transform transform,
                              fuchsia::hardware::display::Frame src_frame,
                              fuchsia::hardware::display::Frame dest_frame) {
            EXPECT_TRUE(fidl::Equals(src_frame, sources[1]));
            EXPECT_TRUE(fidl::Equals(dest_frame, destinations[1]));
          }));

  // Set the mock display controller functions and wait for messages.
  auto mock = mock_display_controller_.get();
  std::thread server([&mock]() mutable {
    // Since we have 2 rectangles with images, we have to wait for 2 calls to initialize layers,
    // 1 call to set the layers on the display, and 2 calls to set the layer primary positions.
    // This all happens when we call engine_->RenderFrame() below.
    for (uint32_t i = 0; i < 5; i++) {
      mock->WaitForMessage();
    }
  });

  engine_->AddDisplay(display_id, parent_root_handle, resolution);
  engine_->RenderFrame();

  server.join();
}

}  // namespace test
}  // namespace flatland
