// 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/lib/ui/gfx/resources/view_holder.h"

#include "garnet/lib/ui/gfx/engine/engine.h"
#include "garnet/lib/ui/gfx/engine/object_linker.h"
#include "garnet/lib/ui/gfx/engine/session.h"
#include "garnet/lib/ui/gfx/resources/nodes/node.h"
#include "garnet/lib/ui/gfx/resources/view.h"
#include "lib/fxl/logging.h"

namespace scenic_impl {
namespace gfx {

const ResourceTypeInfo ViewHolder::kTypeInfo = {ResourceType::kViewHolder,
                                                "ViewHolder"};

ViewHolder::ViewHolder(Session* session, ResourceId id,
                       ViewLinker::ExportLink link)
    : Resource(session, id, ViewHolder::kTypeInfo), link_(std::move(link)) {
  FXL_DCHECK(link_.valid());
  FXL_DCHECK(!link_.initialized());
}

ViewHolder::~ViewHolder() {
  // The View (if any) cleans things up in its LinkDisconnected handler,
  // including Detaching any grandchild Nodes from the parent.
}

bool ViewHolder::Detach() {
  SetParent(nullptr);
  return true;
}

void ViewHolder::SetParent(Node* parent) {
  // Make sure the parent and child Nodes' connections to each other remain
  // consistent.
  if (view_) {
    if (parent) {
      for (const NodePtr& grandchild : view_->children()) {
        parent->AddChild(grandchild);  // Also detaches from the old parent.
      }
    } else {
      for (const NodePtr& grandchild : view_->children()) {
        grandchild->Detach();
      }
    }
  }
  if (parent_ != nullptr) {
    parent_->EraseViewHolder(fxl::RefPtr<ViewHolder>(this));
  }

  parent_ = parent;
  // The parent has changed, so the Scene might have as well.
  RefreshScene();
}

void ViewHolder::Connect() {
  link_.Initialize(this, fit::bind_member(this, &ViewHolder::LinkResolved),
                   fit::bind_member(this, &ViewHolder::LinkDisconnected));
}

void ViewHolder::SetViewProperties(fuchsia::ui::gfx::ViewProperties props) {
  if (props != view_properties_) {
    view_properties_ = std::move(props);
    if (view_) {
      SendViewPropertiesChangedEvent();
    }
  }
}

void ViewHolder::RefreshScene() {
  Scene* new_scene = parent_ ? parent_->scene() : nullptr;
  if (scene_ == new_scene) {
    return;
  }
  scene_ = new_scene;

  if (!view_) {
    // No view to interact with events.
    return;
  }

  if (scene_) {
    SendViewAttachedToSceneEvent();
  } else {
    // View is no longer part of a scene and therefore cannot render to one.
    SetIsViewRendering(false);
    // Reset the render event so that when the View is reattached to the scene
    // and its children render, this ViewHolder will get the signal.
    ResetRenderEvent();

    SendViewDetachedFromSceneEvent();
  }
}

void ViewHolder::LinkResolved(View* view) {
  // The view will also receive a LinkResolved call, and it will take care of
  // linking up the Nodes.
  FXL_DCHECK(!view_ && view);
  view_ = view;
  // Set the render waiting event on the view.
  ResetRenderEvent();

  SendViewConnectedEvent();

  // If the ViewHolder is already attached to a scene, the linked view is now
  // also attached to the scene. Emit event.
  if (scene_) {
    SendViewAttachedToSceneEvent();
  }

  // This guarantees that the View is notified of any previously-set
  // ViewProperties.  Otherwise, e.g. if the ViewHolder properties were set
  // only once before the link was resolved, the View would never be notified.
  SendViewPropertiesChangedEvent();
}

void ViewHolder::LinkDisconnected() {
  // The child is already dead (or never existed) and it cleans things up in its
  // destructor, including Detaching any grandchild Nodes from the parent.
  view_ = nullptr;

  CloseRenderEvent();
  // Link was disconnected, the view can no longer be rendering. If the state
  // was previously rendering, update with not rendering event.
  SetIsViewRendering(false);

  SendViewDisconnectedEvent();
}

void ViewHolder::ResetRenderEvent() {
  FXL_DCHECK(view_);
  // Close any previously set event.
  CloseRenderEvent();

  zx_status_t status = zx::event::create(0u, &render_event_);
  ZX_ASSERT(status == ZX_OK);

  // Re-arm the wait.
  render_waiter_.set_object(render_event_.get());
  render_waiter_.set_trigger(ZX_EVENT_SIGNALED);
  render_waiter_.set_handler([this](async_dispatcher_t*, async::Wait*,
                                    zx_status_t status,
                                    const zx_packet_signal_t*) {
    ZX_ASSERT(status == ZX_OK || status == ZX_ERR_CANCELED);
    if (status == ZX_OK) {
      SetIsViewRendering(true);
    }

    // The first frame has been signaled. Clear the event as it is not used
    // for subsequent frames.
    CloseRenderEvent();
  });
  status = render_waiter_.Begin(async_get_default_dispatcher());
  ZX_ASSERT(status == ZX_OK);

  // Set the event on the View to signal when it is next rendered.
  view_->SetOnRenderEventHandle(render_event_.get());
}

void ViewHolder::CloseRenderEvent() {
  if (view_) {
    view_->InvalidateRenderEventHandle();
  }

  if (render_waiter_.is_pending()) {
    zx_status_t wait_status = render_waiter_.Cancel();
    ZX_ASSERT(wait_status == ZX_OK);
  }
  render_event_.reset();
}

void ViewHolder::SetIsViewRendering(bool is_rendering) {
  if (view_state_.is_rendering == is_rendering) {
    // No state change, return.
    return;
  }
  view_state_.is_rendering = is_rendering;
  SendViewStateChangedEvent();
}

void ViewHolder::SendViewPropertiesChangedEvent() {
  fuchsia::ui::gfx::Event event;
  event.set_view_properties_changed(
      {.view_id = view_->id(), .properties = view_properties_});
  view_->session()->EnqueueEvent(std::move(event));
}

void ViewHolder::SendViewConnectedEvent() {
  fuchsia::ui::gfx::Event event;
  event.set_view_connected({.view_holder_id = id()});
  session()->EnqueueEvent(std::move(event));
}

void ViewHolder::SendViewDisconnectedEvent() {
  fuchsia::ui::gfx::Event event;
  event.set_view_disconnected({.view_holder_id = id()});
  session()->EnqueueEvent(std::move(event));
}

void ViewHolder::SendViewAttachedToSceneEvent() {
  fuchsia::ui::gfx::Event event;
  event.set_view_attached_to_scene(
      {.view_id = view_->id(), .properties = view_properties_});
  view_->session()->EnqueueEvent(std::move(event));
}

void ViewHolder::SendViewDetachedFromSceneEvent() {
  fuchsia::ui::gfx::Event event;
  event.set_view_detached_from_scene({.view_id = view_->id()});
  view_->session()->EnqueueEvent(std::move(event));
}

void ViewHolder::SendViewStateChangedEvent() {
  fuchsia::ui::gfx::Event event;
  event.set_view_state_changed({.view_holder_id = id(), .state = view_state_});
  session()->EnqueueEvent(std::move(event));
}

}  // namespace gfx
}  // namespace scenic_impl
