// Copyright 2024 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 <fidl/fuchsia.ui.composition/cpp/fidl.h>
#include <fidl/fuchsia.ui.views/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/fidl/cpp/interface_ptr.h>
#include <lib/fidl/cpp/wire/internal/thenable.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/syslog/global.h>
#include <lib/syslog/logger.h>
#include <lib/ui/scenic/cpp/view_creation_tokens.h>
#include <lib/ui/scenic/cpp/view_identity.h>
#include <zircon/rights.h>
#include <zircon/status.h>

#include <cstdint>
#include <iostream>

#include "graphical_window.h"

namespace {
// Tag for logging errors
constexpr char kLogTag[] = "reference_session";

// ID for transform
static constexpr uint64_t kRootTransformId = 1;
} // namespace

GraphicalWindow::GraphicalWindow(async_dispatcher_t *dispatcher)
    : dispatcher_(dispatcher) {
  auto graphical_client_end =
      component::Connect<fuchsia_element::GraphicalPresenter>();
  if (graphical_client_end.is_error()) {
    FX_LOGF(ERROR, "kLogTag",
            "Unable to connect to fuchsia_element::Presenter protocol: %s",
            graphical_client_end.status_string());
  }

  presenter_.Bind(std::move(*graphical_client_end), dispatcher_);
  FX_LOG(INFO, kLogTag, "Presenter Binded");

  auto flatland_client_end =
      component::Connect<fuchsia_ui_composition::Flatland>();
  if (flatland_client_end.is_error()) {
    FX_LOGF(
        ERROR, kLogTag,
        "Unable to connect to fuchsia_ui_composition::Flatland protocol: %s",
        flatland_client_end.status_string());
  }

  flatland_.Bind(std::move(*flatland_client_end), dispatcher_);
  FX_LOG(INFO, kLogTag, "Connected to Flatland");
}

void GraphicalWindow::CreateView() {
  FX_LOG(INFO, kLogTag, "Creating View...");

  // Creating Flatland View
  auto [view_token, parent_viewport_token] =
      scenic::ViewCreationTokenPair::New();

  fuchsia_element::ViewSpec view_spec;
  view_spec.viewport_creation_token(fuchsia_ui_views::ViewportCreationToken(
      std::move(parent_viewport_token.value)));

  FX_LOG(INFO, kLogTag, "View Creation Token Created");

  auto parent_viewport_watcher_endpoints =
      fidl::CreateEndpoints<fuchsia_ui_composition::ParentViewportWatcher>();

  auto [parent_viewport_watcher_client_end,
        parent_viewport_watcher_server_end] =
      std::move(parent_viewport_watcher_endpoints.value());
  parent_viewport_watcher_.Bind(std::move(parent_viewport_watcher_client_end),
                                dispatcher_);

  auto create =
      flatland_->CreateView({{.token = std::move(view_token.value),
                              .parent_viewport_watcher = std::move(
                                  parent_viewport_watcher_server_end)}});
  if (create.is_error()) {
    FX_LOGF(ERROR, kLogTag, "Unable to run Create View: %s",
            create.error_value().status_string());
  }
  FX_LOG(INFO, kLogTag, "View Created");

  auto present_flatland =
      flatland_->Present(fuchsia_ui_composition::PresentArgs{});
  if (present_flatland.is_error()) {
    FX_LOGF(ERROR, kLogTag, "Unable to present Flatland: %s",
            present_flatland.error_value().status_string());
  }

  // Attach View to Parent
  presenter_->PresentView({{.view_spec = std::move(view_spec)}})
      .Then([](auto result) {
        if (result.is_error()) {
          FX_LOGF(ERROR, kLogTag, "PresentView failed:");
        }
      });
  FX_LOG(INFO, kLogTag, "View Presented!");

  // Gets size of emulator window and draws square
  GetLayout();
}

void GraphicalWindow::GetLayout() {
  parent_viewport_watcher_->GetLayout().ThenExactlyOnce(
      [&](fidl::Result<fuchsia_ui_composition::ParentViewportWatcher::GetLayout>
              &result) { OnGetLayout(result); });
}

void GraphicalWindow::OnGetLayout(
    fidl::Result<fuchsia_ui_composition::ParentViewportWatcher::GetLayout>
        &result) {
  // Get terminal window size
  if (result.is_ok()) {
    FX_LOGF(INFO, kLogTag, "Layout Received: ");
    int32_t windowWidth =
        static_cast<int32_t>(result->info().logical_size()->width());
    int32_t windowHeight =
        static_cast<int32_t>(result->info().logical_size()->height());
    FX_LOGF(INFO, kLogTag, "Width: %d", windowWidth);
    FX_LOGF(INFO, kLogTag, "Height: %d", windowHeight);

    DrawSquare(windowWidth, windowHeight,
               static_cast<uint32_t>(windowWidth / 5));
  }
}

void GraphicalWindow::DrawSquare(int32_t window_width, int32_t window_height,
                                 uint32_t square_size) {
  // Create ID for square
  const fuchsia_ui_composition::ContentId kFilledRectId = {1};

  // Create Transform and set to root transform
  auto create_transform = flatland_->CreateTransform(
      fuchsia_ui_composition::TransformId({.value = kRootTransformId}));
  if (create_transform.is_error()) {
    FX_LOGF(ERROR, kLogTag, "Unable to run Create Transform: %s",
            create_transform.error_value().status_string());
  };

  auto root_transform = flatland_->SetRootTransform(
      fuchsia_ui_composition::TransformId({.value = kRootTransformId}));
  if (root_transform.is_error()) {
    FX_LOGF(ERROR, kLogTag, "Unable to run Root Transform: %s",
            root_transform.error_value().status_string());
  };
  FX_LOG(INFO, kLogTag, "Transform Created");

  // Move square towards middle of terminal window
  auto set_region = flatland_->SetTranslation(
      {fuchsia_ui_composition::TransformId({.value = kRootTransformId}),
       {static_cast<int32_t>((window_width / 2) - (square_size / 2)),
        static_cast<int32_t>((window_height / 2) - (square_size / 2))}});

  if (set_region.is_error()) {
    FX_LOGF(ERROR, kLogTag, "Unable to Set Region");
  };
  FX_LOG(INFO, kLogTag, "Square Translation Set");

  // Create Square
  auto create_rect = flatland_->CreateFilledRect(kFilledRectId);
  if (create_rect.is_error()) {
    FX_LOGF(ERROR, kLogTag, "Unable to Create Rectangle");
  };

  // Here, you can change the color of the rectangle! Change the color of the
  // rectangle and run the session again to see the change of your color.

  //  R   G  B  Alpha
  // {x, y, z, a}

  // {0.28, 0.46, 1, 1} will give you blue!

  auto set_fill =
      flatland_->SetSolidFill({{kFilledRectId,
                                {1, 0, 1, 1} /* The color fuchsia*/,
                                {square_size, square_size} /* size */}});
  if (set_fill.is_error()) {
    FX_LOGF(ERROR, kLogTag, "Unable to Set Solid Fill");
  };

  // Set Content and Present
  auto set_content = flatland_->SetContent(
      {{fuchsia_ui_composition::TransformId({.value = kRootTransformId}),
        kFilledRectId}});
  if (set_content.is_error()) {
    FX_LOGF(ERROR, kLogTag, "Unable to Set Content");
  };
  FX_LOG(INFO, kLogTag, "Content Created");

  auto present_flatland =
      flatland_->Present(fuchsia_ui_composition::PresentArgs{});
  if (present_flatland.is_error()) {
    FX_LOGF(ERROR, kLogTag, "Unable to present Flatland: %s",
            present_flatland.error_value().status_string());
  }
  FX_LOG(INFO, kLogTag, "View Presented!");
}
