// Copyright 2018 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 "garnet/examples/ui/lab/pose_buffer_presenter/app.h"

// This header is intentionally out of order because it contains a workaround
// for both glm and zircon defining countof(), and must be included before
// the glm headers to work.
#include "src/ui/lib/escher/geometry/types.h"

#include <fuchsia/ui/gfx/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/task.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/quaternion.hpp>
#include <glm/gtx/string_cast.hpp>

#include <iostream>

#include "lib/component/cpp/connect.h"
#include "src/ui/lib/escher/hmd/pose_buffer.h"
#include "src/ui/lib/escher/util/image_utils.h"
#include "lib/ui/scenic/cpp/commands.h"
#include "lib/ui/scenic/cpp/host_memory.h"
#include "lib/ui/scenic/cpp/util/mesh_utils.h"
#include "src/lib/fxl/logging.h"

#define DEBUG_BOX 0

using namespace scenic;

namespace pose_buffer_presenter {

namespace {

constexpr float kSecondsPerNanosecond = .000'000'001f;

static constexpr float kEdgeLength = 0.125f;

static const float kVertexBufferData[] = {
    -1.0f, -1.0f, -1.0f,  // 0
    -1.0f, -1.0f, 1.0f,   // 1
    -1.0f, 1.0f,  -1.0f,  // 2
    -1.0f, 1.0f,  1.0f,   // 3
    1.0f,  -1.0f, -1.0f,  // 4
    1.0f,  -1.0f, 1.0f,   // 5
    1.0f,  1.0f,  -1.0f,  // 6
    1.0f,  1.0f,  1.0f,   // 7
};

static const uint32_t kIndexBufferData[] = {
    5, 6, 7, 6, 5, 4,  // +X
    0, 1, 2, 3, 2, 1,  // -X
    2, 3, 6, 7, 6, 3,  // +Y
    1, 4, 5, 4, 1, 0,  // -Y
    3, 5, 7, 5, 3, 1,  // +Z
    0, 2, 4, 6, 4, 2,  // -Z
};
}  // namespace

App::App(async::Loop* loop)
    : startup_context_(component::StartupContext::CreateFromStartupInfo()),
      loop_(loop) {
  // Connect to the Scenic service.
  scenic_ = startup_context_
                ->ConnectToEnvironmentService<fuchsia::ui::scenic::Scenic>();
  scenic_.set_error_handler([this](zx_status_t status) {
    FXL_LOG(INFO) << "Lost connection to Scenic service. Status: " << status;
    loop_->Quit();
  });
  scenic_->GetDisplayInfo([this](fuchsia::ui::gfx::DisplayInfo display_info) {
    Init(std::move(display_info));
  });
}

void App::CreateExampleScene(float display_width, float display_height) {
  auto session = session_.get();

  // The top-level nesting for drawing anything is compositor -> layer-stack
  // -> layer.  Layer content can come from an image, or by rendering a scene.
  // In this case, we do the latter, so we nest layer -> renderer -> camera ->
  // scene.
  compositor_ = std::make_unique<DisplayCompositor>(session);
  LayerStack layer_stack(session);
  Layer layer(session);
  Renderer renderer(session);
  Scene scene(session);
  camera_ = std::make_unique<StereoCamera>(scene);

  // Produces the Identity View Matrix
  static const glm::vec3 eye(0, 0, 0);
  static const glm::vec3 look_at(0, 0, -1);
  static const glm::vec3 up(0, 1, 0);
  camera_->SetTransform(glm::value_ptr(eye), glm::value_ptr(look_at),
                        glm::value_ptr(up));

  float fovy = glm::radians(30.f);
  float f = 1.0f / tan(0.5f * fovy);
  float aspect_ratio = (display_width * 0.5f) / display_height;
  float near = 0.1;
  float far = 10;
  // Use (display_width * 0.5f) / display_height because the stereo camera uses
  // half of the display for each eye, so the aspect ratio for each eye has 1/2
  // the width:height ratio of the display.
  // clang-format off
  glm::mat4 projection( f / aspect_ratio,  0.0f, 0.0f,                        0.0f,
                        0.0f,                -f, 0.0f,                        0.0f,
                        0.0f,              0.0f, far / (near - far),         -1.0f,
                        0.0f,              0.0f, (near * far) / (near - far), 0.0f);
  // clang-format on

  camera_->SetStereoProjection(glm::value_ptr(projection),
                               glm::value_ptr(projection));

  compositor_->SetLayerStack(layer_stack);
  layer_stack.AddLayer(layer);
  layer.SetSize(display_width, display_height);
  layer.SetRenderer(renderer);
  renderer.SetCamera(camera_->id());
  renderer.SetShadowTechnique(fuchsia::ui::gfx::ShadowTechnique::UNSHADOWED);

  // Set up lights.
  AmbientLight ambient_light(session);
  DirectionalLight directional_light(session);
  scene.AddLight(ambient_light);
  scene.AddLight(directional_light);
  ambient_light.SetColor(0.3f, 0.3f, 0.3f);
  directional_light.SetColor(0.7f, 0.7f, 0.7f);
  directional_light.SetDirection(1.f, 1.f, -2.f);

  // Create an EntityNode to serve as the scene root.
  EntityNode root_node(session);
  scene.AddChild(root_node.id());

  cube_node_ = std::make_unique<ShapeNode>(session);
  Material cube_material(session);
  cube_material.SetColor(0xf5, 0x00, 0x57, 0xff);  // Pink A400
  cube_node_->SetMaterial(cube_material);

  std::vector<float> vertices(std::begin(kVertexBufferData),
                              std::end(kVertexBufferData));
  std::vector<uint32_t> indices(std::begin(kIndexBufferData),
                                std::end(kIndexBufferData));
  auto cube_shape = mesh_utils::NewMeshWithVertices(session, vertices, indices);

  cube_node_->SetShape(*cube_shape);
  // Raw vertex data has an edge length of 2, so we must scale by half of
  // kEdgeLength to end up with a cube whose edge length is kEdgeLength long.
  float scale_factor = 0.5 * kEdgeLength;
  cube_node_->SetScale(scale_factor, scale_factor, scale_factor);
  cube_node_->SetTranslation(0, 4.0 * kEdgeLength, 0);

  root_node.AddChild(*cube_node_);

// Adds a colored box arround the camera to help debug orientation problems
#if DEBUG_BOX
  float pane_width = 10;
  scenic::Rectangle pane_shape(session, pane_width, pane_width);

  static const int num_panes = 6;

  glm::vec4 colors[num_panes] = {
      glm::vec4(255, 0, 0, 255),    // RED
      glm::vec4(0, 255, 255, 255),  // CYAN
      glm::vec4(0, 255, 0, 255),    // GREEN
      glm::vec4(255, 0, 255, 255),  // MAGENTA
      glm::vec4(0, 0, 255, 255),    // BLUE
      glm::vec4(255, 255, 0, 255),  // YELLOW
  };

  static const float pane_offset = pane_width / 2;

  glm::vec3 translations[num_panes] = {
      glm::vec3(0, 0, pane_offset),   // Above Camera
      glm::vec3(0, 0, -pane_offset),  // Below Camera
      glm::vec3(pane_offset, 0, 0),   // Right of camera
      glm::vec3(-pane_offset, 0, 0),  // Left of Camera
      glm::vec3(0, pane_offset, 0),   // In front of camera.
      glm::vec3(0, -pane_offset, 0),  // Behind camera.
  };

  float pi = glm::pi<float>();
  glm::quat orientations[num_panes] = {
      glm::quat(),  // identity quaternion
      glm::angleAxis(pi, glm::vec3(1, 0, 0)),
      glm::angleAxis(pi / 2, glm::vec3(0, 1, 0)),
      glm::angleAxis(-pi / 2, glm::vec3(0, 1, 0)),
      glm::angleAxis(-pi / 2, glm::vec3(1, 0, 0)),
      glm::angleAxis(pi / 2, glm::vec3(1, 0, 0)),

  };

  for (int i = 0; i < num_panes; i++) {
    glm::vec4 color = colors[i];
    glm::vec3 translation = translations[i];
    glm::quat orientation = orientations[i];

    scenic::Material pane_material(session);
    pane_material.SetColor(color.r, color.g, color.b, color.a);
    scenic::ShapeNode pane_shape_node(session);
    pane_shape_node.SetShape(pane_shape);
    pane_shape_node.SetMaterial(pane_material);
    pane_shape_node.SetTranslation(translation.x, translation.y, translation.z);
    pane_shape_node.SetRotation(orientation.x, orientation.y, orientation.z,
                                orientation.w);
    root_node.AddChild(pane_shape_node);
  }
#endif
}

void App::StartPoseBufferProvider() {
  FXL_LOG(INFO) << "Launching PoseBufferProvider";

  fuchsia::sys::LaunchInfo launch_info;
  launch_info.url =
      "fuchsia-pkg://fuchsia.com/pose_buffer_provider#meta/"
      "pose_buffer_provider.cmx";
  launch_info.directory_request = services_.NewRequest();
  startup_context_->launcher()->CreateComponent(std::move(launch_info),
                                                controller_.NewRequest());
  controller_.set_error_handler([](zx_status_t status) {
    FXL_LOG(ERROR) << "Lost connection to controller_. Status: " << status;
  });

  services_.ConnectToService(provider_.NewRequest().TakeChannel(),
                             fuchsia::ui::gfx::PoseBufferProvider::Name_);

  provider_.set_error_handler([](zx_status_t status) {
    FXL_LOG(ERROR) << "Lost connection to PoseBufferProvider service. Status: "
                   << status;
  });
}

void App::ConfigurePoseBuffer() {
  auto session = session_.get();

  uint64_t vmo_size = PAGE_SIZE;
  zx::vmo vmo;
  zx_status_t status;
  status = zx::vmo::create(vmo_size, 0u, &pose_buffer_vmo_);
  FXL_DCHECK(status == ZX_OK);
  status = pose_buffer_vmo_.duplicate(ZX_RIGHT_SAME_RIGHTS, &vmo);
  FXL_DCHECK(status == ZX_OK);

  zx_time_t base_time = zx::clock::get_monotonic().get();
  // Normally the time interval is the period of time between each entry in the
  // pose buffer. In this example we only use one entry so the time interval is
  // pretty meaningless. Set to 1 for simplicity (see ARGO-21).
  zx_time_t time_interval = 1;
  uint32_t num_entries = 1;

  Memory mem(session, std::move(vmo), vmo_size,
             fuchsia::images::MemoryType::VK_DEVICE_MEMORY);
  Buffer pose_buffer(mem, 0, vmo_size);

  camera_->SetPoseBuffer(pose_buffer, num_entries, base_time, time_interval);

  status = pose_buffer_vmo_.duplicate(ZX_RIGHT_SAME_RIGHTS, &vmo);
  FXL_DCHECK(status == ZX_OK);

  provider_->SetPoseBuffer(std::move(vmo), num_entries, base_time,
                           time_interval);
}

void App::Init(fuchsia::ui::gfx::DisplayInfo display_info) {
  StartPoseBufferProvider();
  FXL_LOG(INFO) << "Creating new Session";

  // TODO: set up SessionListener.
  session_ = std::make_unique<Session>(scenic_.get());
  session_->set_error_handler([this](zx_status_t status) {
    FXL_LOG(INFO) << "Session terminated. Status: " << status;
    loop_->Quit();
  });

  // Set up initial scene.
  const float display_width = static_cast<float>(display_info.width_in_px);
  const float display_height = static_cast<float>(display_info.height_in_px);
  CreateExampleScene(display_width, display_height);
  ConfigurePoseBuffer();

  start_time_ = zx_clock_get_monotonic();
  Update(start_time_);
}

void App::Update(uint64_t next_presentation_time) {
  float secs = zx_clock_get_monotonic() * kSecondsPerNanosecond;

  glm::quat quaternion =
      glm::angleAxis(secs / 2.0f, glm::normalize(glm::vec3(0, 1, 0)));

  cube_node_->SetRotation(quaternion.x, quaternion.y, quaternion.z,
                          quaternion.w);

  // Present
  session_->Present(
      next_presentation_time, [this](fuchsia::images::PresentationInfo info) {
        Update(info.presentation_time + info.presentation_interval);
      });
}

void App::ReleaseSessionResources() {
  FXL_LOG(INFO) << "Closing session.";

  compositor_.reset();
  camera_.reset();

  session_.reset();
}

}  // namespace pose_buffer_presenter
