// 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/cpp/macros.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_LOGST(ERROR, kLogTag)
        << "Unable to connect to fuchsia_element::Presenter protocol: "
        << graphical_client_end.status_string();
  }

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

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

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

void GraphicalWindow::CreateView() {
  FX_LOGST(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_LOGST(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_LOGST(ERROR, kLogTag)
        << "Unable to run Create View: " << create.error_value();
  }
  FX_LOGST(INFO, kLogTag) << "View Created";

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

  // Attach View to Parent
  presenter_->PresentView({{.view_spec = std::move(view_spec)}})
      .Then([](auto result) {
        if (result.is_error()) {
          FX_LOGST(ERROR, kLogTag)
              << "PresentView failed: " << result.error_value();
        }
      });
  FX_LOGST(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_LOGST(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_LOGST(INFO, kLogTag) << "Width: " << windowWidth;
    FX_LOGST(INFO, kLogTag) << "Height: " << 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_LOGST(ERROR, kLogTag)
        << "Unable to run Create Transform: " << create_transform.error_value();
  };

  auto root_transform = flatland_->SetRootTransform(
      fuchsia_ui_composition::TransformId({.value = kRootTransformId}));
  if (root_transform.is_error()) {
    FX_LOGST(ERROR, kLogTag)
        << "Unable to run Root Transform: " << root_transform.error_value();
  };
  FX_LOGST(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_LOGST(ERROR, kLogTag) << "Unable to Set Region";
  };
  FX_LOGST(INFO, kLogTag) << "Square Translation Set";

  // Create Square
  auto create_rect = flatland_->CreateFilledRect(kFilledRectId);
  if (create_rect.is_error()) {
    FX_LOGST(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_LOGST(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_LOGST(ERROR, kLogTag) << "Unable to Set Content";
  };
  FX_LOGST(INFO, kLogTag) << "Content Created";

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