// 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 <src/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;
}
