// Copyright 2019 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 <math.h>

#include <fuchsia/ui/app/cpp/fidl.h>
#include <fuchsia/ui/gfx/cpp/fidl.h>
#include <fuchsia/ui/input/cpp/fidl.h>
#include <fuchsia/ui/scenic/cpp/fidl.h>
#include <fuchsia/ui/views/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/component/cpp/startup_context.h>
#include <lib/fxl/logging.h>
#include <lib/ui/scenic/cpp/commands.h>
#include <lib/ui/scenic/cpp/view_token_pair.h>

class BouncingBallView : public fuchsia::ui::scenic::SessionListener {
 public:
  BouncingBallView(component::StartupContext* startup_context,
                   fuchsia::ui::views::ViewToken view_token)
      : session_listener_binding_(this) {
    // Connect to Scenic.
    fuchsia::ui::scenic::ScenicPtr scenic =
        startup_context
            ->ConnectToEnvironmentService<fuchsia::ui::scenic::Scenic>();

    // Create a Scenic Session and a Scenic SessionListener.
    scenic->CreateSession(session_.NewRequest(),
                          session_listener_binding_.NewBinding());

    InitializeScene(std::move(view_token));
  }

 private:
  static void PushCommand(std::vector<fuchsia::ui::scenic::Command>* cmds,
                          fuchsia::ui::gfx::Command cmd) {
    // Wrap the gfx::Command in a scenic::Command, then push it.
    cmds->push_back(scenic::NewCommand(std::move(cmd)));
  }

  void InitializeScene(fuchsia::ui::views::ViewToken view_token) {
    // Build up a list of commands we will send over our Scenic Session.
    std::vector<fuchsia::ui::scenic::Command> cmds;

    // View: Use |view_token| to create a View in the Session.
    PushCommand(&cmds, scenic::NewCreateViewCmd(kViewId, std::move(view_token),
                                                "bouncing_circle_view"));

    // Root Node.
    PushCommand(&cmds, scenic::NewCreateEntityNodeCmd(kRootNodeId));
    PushCommand(&cmds, scenic::NewAddChildCmd(kViewId, kRootNodeId));

    // Background Material.
    PushCommand(&cmds, scenic::NewCreateMaterialCmd(kBgMaterialId));
    PushCommand(&cmds, scenic::NewSetColorCmd(kBgMaterialId, 0xf5, 0x00, 0x57,
                                              0xff));  // Pink A400

    // Background ShapeNode.
    PushCommand(&cmds, scenic::NewCreateShapeNodeCmd(kBgNodeId));
    PushCommand(&cmds, scenic::NewSetMaterialCmd(kBgNodeId, kBgMaterialId));
    PushCommand(&cmds, scenic::NewAddChildCmd(kRootNodeId, kBgNodeId));

    // Circle's Material.
    PushCommand(&cmds, scenic::NewCreateMaterialCmd(kCircleMaterialId));
    PushCommand(&cmds,
                scenic::NewSetColorCmd(kCircleMaterialId, 0x67, 0x3a, 0xb7,
                                       0xff));  // Deep Purple 500

    // Circle's ShapeNode.
    PushCommand(&cmds, scenic::NewCreateShapeNodeCmd(kCircleNodeId));
    PushCommand(&cmds,
                scenic::NewSetMaterialCmd(kCircleNodeId, kCircleMaterialId));
    PushCommand(&cmds, scenic::NewAddChildCmd(kRootNodeId, kCircleNodeId));

    session_->Enqueue(std::move(cmds));

    // Apply all the commands we've enqueued by calling Present. For this first
    // frame we call Present with a presentation_time = 0 which means it the
    // commands should be applied immediately. For future frames, we'll use the
    // timing information we receive to have precise presentation times.
    session_->Present(0, {}, {},
                      [this](fuchsia::images::PresentationInfo info) {
                        OnPresent(std::move(info));
                      });
  }

  // |fuchsia::ui::scenic::SessionListener|
  void OnScenicError(std::string error) override {}

  static bool IsViewPropertiesChangedEvent(
      const fuchsia::ui::scenic::Event& event) {
    return event.Which() == fuchsia::ui::scenic::Event::Tag::kGfx &&
           event.gfx().Which() ==
               fuchsia::ui::gfx::Event::Tag::kViewPropertiesChanged;
  }

  static bool IsPointerEvent(const fuchsia::ui::scenic::Event& event) {
    return event.Which() == fuchsia::ui::scenic::Event::Tag::kInput &&
           event.input().Which() ==
               fuchsia::ui::input::InputEvent::Tag::kPointer;
  }

  static bool IsPointerDownEvent(const fuchsia::ui::scenic::Event& event) {
    return IsPointerEvent(event) &&
           event.input().pointer().phase ==
               fuchsia::ui::input::PointerEventPhase::DOWN;
  }

  static bool IsPointerUpEvent(const fuchsia::ui::scenic::Event& event) {
    return IsPointerEvent(event) &&
           event.input().pointer().phase ==
               fuchsia::ui::input::PointerEventPhase::UP;
  }

  // |fuchsia::ui::scenic::SessionListener|
  void OnScenicEvent(std::vector<fuchsia::ui::scenic::Event> events) override {
    for (auto& event : events) {
      if (IsViewPropertiesChangedEvent(event)) {
        OnViewPropertiesChanged(
            event.gfx().view_properties_changed().properties);
      } else if (IsPointerDownEvent(event)) {
        pointer_down_ = true;
        pointer_id_ = event.input().pointer().pointer_id;
      } else if (IsPointerUpEvent(event)) {
        if (pointer_id_ == event.input().pointer().pointer_id) {
          pointer_down_ = false;
        }
      } else {
        // Unhandled event.
      }
    }
  }

  void OnViewPropertiesChanged(fuchsia::ui::gfx::ViewProperties vp) {
    view_width_ = (vp.bounding_box.max.x - vp.inset_from_max.x) -
                  (vp.bounding_box.min.x + vp.inset_from_min.x);
    view_height_ = (vp.bounding_box.max.y - vp.inset_from_max.y) -
                   (vp.bounding_box.min.y + vp.inset_from_min.y);

    // Position is relative to the View's origin system.
    const float center_x = view_width_ * .5f;
    const float center_y = view_height_ * .5f;

    // Build up a list of commands we will send over our Scenic Session.
    std::vector<fuchsia::ui::scenic::Command> cmds;

    // Background Shape.
    const int bg_shape_id = new_resource_id_++;
    PushCommand(&cmds, scenic::NewCreateRectangleCmd(bg_shape_id, view_width_,
                                                     view_height_));
    PushCommand(&cmds, scenic::NewSetShapeCmd(kBgNodeId, bg_shape_id));

    // We release the Shape Resource here, but it continues to stay alive in
    // Scenic because it's being referenced by background ShapeNode (i.e. the
    // one with id kBgNodeId). However, we no longer have a way to reference it.
    //
    // Once the background ShapeNode no longer references this shape, because a
    // new Shape was set on it, this Shape will be destroyed internally in
    // Scenic.
    PushCommand(&cmds, scenic::NewReleaseResourceCmd(bg_shape_id));

    // Translate the background node.
    constexpr float kBackgroundElevation = 0.f;
    PushCommand(&cmds, scenic::NewSetTranslationCmd(
                           kBgNodeId, (float[]){center_x, center_y,
                                                -kBackgroundElevation}));

    // Circle Shape.
    circle_radius_ = std::min(view_width_, view_height_) * .1f;
    const int circle_shape_id = new_resource_id_++;
    PushCommand(&cmds,
                scenic::NewCreateCircleCmd(circle_shape_id, circle_radius_));
    PushCommand(&cmds, scenic::NewSetShapeCmd(kCircleNodeId, circle_shape_id));

    // We release the Shape Resource here, but it continues to stay alive in
    // Scenic because it's being referenced by circle's ShapeNode (i.e. the one
    // with id kCircleNodeId). However, we no longer have a way to reference it.
    //
    // Once the background ShapeNode no longer references this shape, because a
    // new Shape was set on it, this Shape will be destroyed internally in
    // Scenic.
    PushCommand(&cmds, scenic::NewReleaseResourceCmd(circle_shape_id));

    session_->Enqueue(std::move(cmds));

    // The commands won't actually get committed until Session.Present() is
    // called. However, since we're animating every frame, in this case we can
    // assume Present() will be called shortly.
  }

  void UpdateCirclePosition(float t) {
    if (pointer_down_) {
      // Move back to near initial position and velocity when there's a pointer
      // down event.
      circle_pos_x_ = initialCirclePosX;
      circle_pos_y_ = initialCirclePosY;
      circle_velocity_y_ = 0.f;
      return;
    }
    constexpr float kYAcceleration = 3.f;
    circle_velocity_y_ += kYAcceleration * t;

    constexpr float kCircleVelocityX = 0.2;
    circle_pos_x_ += kCircleVelocityX * t;
    circle_pos_y_ += fmin(circle_velocity_y_ * t, 1.f);

    if (circle_pos_y_ > 1.f) {
      // Bounce.
      circle_velocity_y_ *= -0.8f;
      circle_pos_y_ = 1.f;
    }
    if (circle_pos_y_ >= 0.999f && fabs(circle_velocity_y_) < .015f) {
      // If the circle stops bouncing, start the simulation again.
      circle_pos_y_ = 0.f;
      circle_velocity_y_ = 0.f;
    }
    if (circle_pos_x_ > 1) {
      // Wrap the x position.
      circle_pos_x_ = fmod(circle_pos_x_, 1.f);
    }
  }

  void OnPresent(fuchsia::images::PresentationInfo presentation_info) {
    uint64_t presentation_time = presentation_info.presentation_time;

    constexpr float kSecondsPerNanosecond = .000'000'001f;
    float t =
        (presentation_time - last_presentation_time_) * kSecondsPerNanosecond;
    if (last_presentation_time_ == 0) {
      t = 0;
    }
    last_presentation_time_ = presentation_time;

    std::vector<fuchsia::ui::scenic::Command> cmds;

    UpdateCirclePosition(t);
    const float circle_pos_x_absolute = circle_pos_x_ * view_width_;
    const float circle_pos_y_absolute =
        circle_pos_y_ * view_height_ - circle_radius_;

    // Translate the circle's node.
    constexpr float kCircleElevation = 8.f;
    PushCommand(&cmds, scenic::NewSetTranslationCmd(
                           kCircleNodeId, (float[]){circle_pos_x_absolute,
                                                    circle_pos_y_absolute,
                                                    -kCircleElevation}));
    session_->Enqueue(std::move(cmds));

    zx_time_t next_presentation_time = presentation_info.presentation_time +
                                       presentation_info.presentation_interval;
    session_->Present(next_presentation_time, {}, {},
                      [this](fuchsia::images::PresentationInfo info) {
                        OnPresent(std::move(info));
                      });
  }

  const int kViewId = 1;
  const int kRootNodeId = 2;
  const int kBgMaterialId = 3;
  const int kBgNodeId = 4;
  const int kCircleMaterialId = 5;
  const int kCircleNodeId = 6;

  // For other resources we create, we use |new_resource_id_| and then increment
  // it.
  int new_resource_id_ = 7;

  uint64_t last_presentation_time_ = 0;

  float view_width_ = 0;
  float view_height_ = 0;

  // Position is in the range [0, 1] and then multiplied by (view_width_,
  // view_height_).
  static constexpr float initialCirclePosX = 0.12f;
  static constexpr float initialCirclePosY = 0.26f;
  float circle_pos_x_ = initialCirclePosX;
  float circle_pos_y_ = initialCirclePosY;

  float circle_velocity_y_ = 0.f;

  // Circle's radius in logical pixels.
  float circle_radius_ = 0.f;

  // Input.
  bool pointer_down_ = false;
  uint32_t pointer_id_ = 0;

  fidl::Binding<fuchsia::ui::scenic::SessionListener> session_listener_binding_;
  fuchsia::ui::scenic::SessionPtr session_;
};

// Implement the ViewProvider interface, a standard way for an embedder to
// provide us a token that, using Scenic APIs, allows us to create a View
// that's attached to the embedder's ViewHolder.
class ViewProviderService : public fuchsia::ui::app::ViewProvider {
 public:
  ViewProviderService(component::StartupContext* startup_context)
      : startup_context_(startup_context) {}

  // |fuchsia::ui::app::ViewProvider|
  void CreateView(
      zx::eventpair view_token,
      fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> incoming_services,
      fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> outgoing_services)
      override {
    auto view = std::make_unique<BouncingBallView>(
        startup_context_, scenic::ToViewToken(std::move(view_token)));
    views_.push_back(std::move(view));
  }

  void HandleViewProviderRequest(
      fidl::InterfaceRequest<fuchsia::ui::app::ViewProvider> request) {
    bindings_.AddBinding(this, std::move(request));
  }

 private:
  component::StartupContext* startup_context_ = nullptr;
  std::vector<std::unique_ptr<BouncingBallView>> views_;
  fidl::BindingSet<ViewProvider> bindings_;
};

int main(int argc, const char** argv) {
  async::Loop loop(&kAsyncLoopConfigAttachToThread);

  std::unique_ptr<component::StartupContext> startup_context =
      component::StartupContext::CreateFromStartupInfo();

  ViewProviderService view_provider(startup_context.get());

  // Add our ViewProvider service to the outgoing services.
  startup_context->outgoing().AddPublicService<fuchsia::ui::app::ViewProvider>(
      [&view_provider](
          fidl::InterfaceRequest<fuchsia::ui::app::ViewProvider> request) {
        view_provider.HandleViewProviderRequest(std::move(request));
      });

  loop.Run();
  return 0;
}
