// Copyright 2017 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 <lib/images/cpp/images.h>
#include <lib/ui/scenic/cpp/commands.h>
#include <lib/ui/scenic/cpp/resources.h>
#include <lib/ui/scenic/cpp/view_token_pair.h>

#include <algorithm>

namespace scenic {
namespace {

template <class T>
constexpr const T& clamp(const T& v, const T& lo, const T& hi) {
  return (v < lo) ? lo : (hi < v) ? hi : v;
}

}  // namespace

Resource::Resource(Session* session) : session_(session), id_(session->AllocResourceId()) {}

Resource::Resource(Resource&& moved) noexcept : session_(moved.session_), id_(moved.id_) {
  auto& moved_session = *const_cast<Session**>(&moved.session_);
  auto& moved_id = *const_cast<uint32_t*>(&moved.id_);
  moved_session = nullptr;
  moved_id = 0;
}

Resource::~Resource() {
  // If this resource was moved, it is not responsible for releasing the ID.
  if (session_)
    session_->ReleaseResource(id_);
}

void Resource::Export(zx::eventpair export_token) {
  session_->Enqueue(NewExportResourceCmd(id(), std::move(export_token)));
}

void Resource::ExportAsRequest(zx::eventpair* out_import_token) {
  session_->Enqueue(NewExportResourceCmdAsRequest(id(), out_import_token));
}

void Resource::SetEventMask(uint32_t event_mask) {
  session_->Enqueue(NewSetEventMaskCmd(id(), event_mask));
}

void Resource::SetLabel(const std::string& label) {
  session_->Enqueue(NewSetLabelCmd(id(), label));
}

Shape::Shape(Session* session) : Resource(session) {}

Shape::Shape(Shape&& moved) noexcept : Resource(std::move(moved)) {}

Shape::~Shape() = default;

Circle::Circle(Session* session, float radius) : Shape(session) {
  session->Enqueue(NewCreateCircleCmd(id(), radius));
}

Circle::Circle(Circle&& moved) noexcept : Shape(std::move(moved)) {}

Circle::~Circle() = default;

Rectangle::Rectangle(Session* session, float width, float height) : Shape(session) {
  session->Enqueue(NewCreateRectangleCmd(id(), width, height));
}

Rectangle::Rectangle(Rectangle&& moved) noexcept : Shape(std::move(moved)) {}

Rectangle::~Rectangle() = default;

RoundedRectangle::RoundedRectangle(Session* session, float width, float height,
                                   float top_left_radius, float top_right_radius,
                                   float bottom_right_radius, float bottom_left_radius)
    : Shape(session) {
  session->Enqueue(NewCreateRoundedRectangleCmd(id(), width, height, top_left_radius,
                                                top_right_radius, bottom_right_radius,
                                                bottom_left_radius));
}

RoundedRectangle::RoundedRectangle(RoundedRectangle&& moved) noexcept : Shape(std::move(moved)) {}

RoundedRectangle::~RoundedRectangle() = default;

Image::Image(const Memory& memory, off_t memory_offset, fuchsia::images::ImageInfo info)
    : Image(memory.session(), memory.id(), memory_offset, info) {}

Image::Image(Session* session, uint32_t memory_id, off_t memory_offset,
             fuchsia::images::ImageInfo info)
    : Resource(session), memory_offset_(memory_offset), info_(info) {
  session->Enqueue(NewCreateImageCmd(id(), memory_id, memory_offset_, info));
}

Image::Image(Image&& moved) noexcept
    : Resource(std::move(moved)), memory_offset_(moved.memory_offset_), info_(moved.info_) {}

Image::~Image() = default;

size_t Image::ComputeSize(const fuchsia::images::ImageInfo& image_info) {
  return images::ImageSize(image_info);
}

Buffer::Buffer(const Memory& memory, off_t memory_offset, size_t num_bytes)
    : Buffer(memory.session(), memory.id(), memory_offset, num_bytes) {}

Buffer::Buffer(Session* session, uint32_t memory_id, off_t memory_offset, size_t num_bytes)
    : Resource(session) {
  session->Enqueue(NewCreateBufferCmd(id(), memory_id, memory_offset, num_bytes));
}

Buffer::Buffer(Buffer&& moved) noexcept : Resource(std::move(moved)) {}

Buffer::~Buffer() = default;

Memory::Memory(Session* session, zx::vmo vmo, uint64_t allocation_size,
               fuchsia::images::MemoryType memory_type)
    : Resource(session), memory_type_(memory_type) {
  session->Enqueue(NewCreateMemoryCmd(id(), std::move(vmo), allocation_size, memory_type));
}

Memory::Memory(Memory&& moved) noexcept
    : Resource(std::move(moved)), memory_type_(moved.memory_type_) {}

Memory::~Memory() = default;

Mesh::Mesh(Session* session) : Shape(session) { session->Enqueue(NewCreateMeshCmd(id())); }

Mesh::Mesh(Mesh&& moved) noexcept : Shape(std::move(moved)) {}

Mesh::~Mesh() = default;

void Mesh::BindBuffers(const Buffer& index_buffer, fuchsia::ui::gfx::MeshIndexFormat index_format,
                       uint64_t index_offset, uint32_t index_count, const Buffer& vertex_buffer,
                       fuchsia::ui::gfx::MeshVertexFormat vertex_format, uint64_t vertex_offset,
                       uint32_t vertex_count, const std::array<float, 3>& bounding_box_min,
                       const std::array<float, 3>& bounding_box_max) {
  ZX_DEBUG_ASSERT(session() == index_buffer.session() && session() == vertex_buffer.session());
  session()->Enqueue(NewBindMeshBuffersCmd(
      id(), index_buffer.id(), index_format, index_offset, index_count, vertex_buffer.id(),
      vertex_format, vertex_offset, vertex_count, bounding_box_min, bounding_box_max));
}

Material::Material(Session* session) : Resource(session) {
  session->Enqueue(NewCreateMaterialCmd(id()));
}

Material::Material(Material&& moved) noexcept : Resource(std::move(moved)) {}

Material::~Material() = default;

void Material::SetTexture(uint32_t image_id) {
  session()->Enqueue(NewSetTextureCmd(id(), image_id));
}

void Material::SetColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) {
  session()->Enqueue(NewSetColorCmd(id(), red, green, blue, alpha));
}

Node::Node(Session* session) : Resource(session) {}

Node::Node(Node&& moved) noexcept : Resource(std::move(moved)) {}

Node::~Node() = default;

void Node::SetTranslation(const std::array<float, 3>& translation) {
  session()->Enqueue(NewSetTranslationCmd(id(), translation));
}

void Node::SetTranslation(uint32_t variable_id) {
  session()->Enqueue(NewSetTranslationCmd(id(), variable_id));
}

void Node::SetScale(const std::array<float, 3>& scale) {
  session()->Enqueue(NewSetScaleCmd(id(), scale));
}
void Node::SetScale(uint32_t variable_id) { session()->Enqueue(NewSetScaleCmd(id(), variable_id)); }

void Node::SetRotation(const std::array<float, 4>& quaternion) {
  session()->Enqueue(NewSetRotationCmd(id(), quaternion));
}

void Node::SetRotation(uint32_t variable_id) {
  session()->Enqueue(NewSetRotationCmd(id(), variable_id));
}

void Node::SetAnchor(const std::array<float, 3>& anchor) {
  session()->Enqueue(NewSetAnchorCmd(id(), anchor));
}

void Node::SetAnchor(uint32_t variable_id) {
  session()->Enqueue(NewSetAnchorCmd(id(), variable_id));
}

void Node::SendSizeChangeHint(float width_change_factor, float height_change_factor) {
  session()->Enqueue(NewSendSizeChangeHintCmdHACK(id(), width_change_factor, height_change_factor));
}

void Node::SetTag(uint32_t tag_value) { session()->Enqueue(NewSetTagCmd(id(), tag_value)); }

void Node::SetHitTestBehavior(fuchsia::ui::gfx::HitTestBehavior hit_test_behavior) {
  session()->Enqueue(NewSetHitTestBehaviorCmd(id(), hit_test_behavior));
}

void Node::SetSemanticVisibility(bool visible) {
  session()->Enqueue(NewSetSemanticVisibilityCmd(id(), visible));
}

void Node::Detach() { session()->Enqueue(NewDetachCmd(id())); }

ShapeNode::ShapeNode(Session* session) : Node(session) {
  session->Enqueue(NewCreateShapeNodeCmd(id()));
}

ShapeNode::ShapeNode(ShapeNode&& moved) noexcept : Node(std::move(moved)) {}

ShapeNode::~ShapeNode() = default;

void ShapeNode::SetShape(uint32_t shape_id) { session()->Enqueue(NewSetShapeCmd(id(), shape_id)); }

void ShapeNode::SetMaterial(uint32_t material_id) {
  session()->Enqueue(NewSetMaterialCmd(id(), material_id));
}

ContainerNode::ContainerNode(Session* session) : Node(session) {}

ContainerNode::ContainerNode(ContainerNode&& moved) noexcept : Node(std::move(moved)) {}

ContainerNode::~ContainerNode() = default;

void ContainerNode::AddChild(uint32_t child_node_id) {
  session()->Enqueue(NewAddChildCmd(id(), child_node_id));
}

void ContainerNode::DetachChildren() { session()->Enqueue(NewDetachChildrenCmd(id())); }

EntityNode::EntityNode(Session* session) : ContainerNode(session) {
  session->Enqueue(NewCreateEntityNodeCmd(id()));
}

EntityNode::EntityNode(EntityNode&& moved) noexcept : ContainerNode(std::move(moved)) {}

EntityNode::~EntityNode() = default;

void EntityNode::Attach(const ViewHolder& view_holder) { AddChild(view_holder); }

void EntityNode::SetClip(uint32_t clip_id, bool clip_to_self) {
  session()->Enqueue(NewSetClipCmd(id(), clip_id, clip_to_self));
}

void EntityNode::SetClipPlanes(std::vector<fuchsia::ui::gfx::Plane3> planes) {
  session()->Enqueue(NewSetClipPlanesCmd(id(), std::move(planes)));
}

ImportNode::ImportNode(Session* session) : ContainerNode(session) {}

ImportNode::ImportNode(ImportNode&& moved) noexcept : ContainerNode(std::move(moved)) {}

ImportNode::~ImportNode() { ZX_DEBUG_ASSERT_MSG(is_bound_, "Import was never bound."); }

void ImportNode::Bind(zx::eventpair import_token) {
  ZX_DEBUG_ASSERT(!is_bound_);
  session()->Enqueue(
      NewImportResourceCmd(id(), fuchsia::ui::gfx::ImportSpec::NODE, std::move(import_token)));
  is_bound_ = true;
}

void ImportNode::BindAsRequest(zx::eventpair* out_export_token) {
  ZX_DEBUG_ASSERT(!is_bound_);
  session()->Enqueue(
      NewImportResourceCmdAsRequest(id(), fuchsia::ui::gfx::ImportSpec::NODE, out_export_token));
  is_bound_ = true;
}

void ImportNode::Attach(const ViewHolder& view_holder) {
  session()->Enqueue(NewAddChildCmd(id(), view_holder.id()));
}

ViewHolder::ViewHolder(Session* session, zx::eventpair token, const std::string& debug_name)
    : Node(session) {
  session->Enqueue(
      NewCreateViewHolderCmd(id(), scenic::ToViewHolderToken(std::move(token)), debug_name));
}

ViewHolder::ViewHolder(Session* session, fuchsia::ui::views::ViewHolderToken token,
                       const std::string& debug_name)
    : Node(session) {
  session->Enqueue(NewCreateViewHolderCmd(id(), std::move(token), debug_name));
}

ViewHolder::ViewHolder(ViewHolder&& moved) noexcept : Node(std::move(moved)) {}

ViewHolder::~ViewHolder() = default;

void ViewHolder::SetViewProperties(const std::array<float, 3>& bounding_box_min,
                                   const std::array<float, 3>& bounding_box_max,
                                   const std::array<float, 3>& inset_from_min,
                                   const std::array<float, 3>& inset_from_max) {
  session()->Enqueue(NewSetViewPropertiesCmd(id(), bounding_box_min, bounding_box_max,
                                             inset_from_min, inset_from_max));
}
void ViewHolder::SetViewProperties(const fuchsia::ui::gfx::ViewProperties& props) {
  session()->Enqueue(NewSetViewPropertiesCmd(id(), props));
}

void ViewHolder::SetDebugBoundsColor(uint8_t red, uint8_t green, uint8_t blue) {
  session()->Enqueue(NewSetViewHolderBoundsColorCmd(id(), red, green, blue));
}

View::View(Session* session, zx::eventpair token, const std::string& debug_name)
    : Resource(session) {
  session->Enqueue(NewCreateViewCmd(id(), scenic::ToViewToken(std::move(token)), debug_name));
}

View::View(Session* session, fuchsia::ui::views::ViewToken token, const std::string& debug_name)
    : Resource(session) {
  session->Enqueue(NewCreateViewCmd(id(), std::move(token), debug_name));
}

View::View(Session* session, fuchsia::ui::views::ViewToken token,
           fuchsia::ui::views::ViewRefControl control_ref, fuchsia::ui::views::ViewRef view_ref,
           const std::string& debug_name)
    : Resource(session) {
  session->Enqueue(NewCreateViewCmd(id(), std::move(token), std::move(control_ref),
                                    std::move(view_ref), debug_name));
}

View::View(View&& moved) noexcept : Resource(std::move(moved)) {}

View::~View() = default;

void View::AddChild(const Node& child) const {
  ZX_DEBUG_ASSERT(session() == child.session());
  session()->Enqueue(NewAddChildCmd(id(), child.id()));
}

void View::DetachChild(const Node& child) const {
  ZX_DEBUG_ASSERT(session() == child.session());
  session()->Enqueue(NewDetachCmd(child.id()));
}

void View::enableDebugBounds(bool enable) {
  session()->Enqueue(NewSetEnableDebugViewBoundsCmd(id(), enable));
}

ClipNode::ClipNode(Session* session) : ContainerNode(session) {
  session->Enqueue(NewCreateClipNodeCmd(id()));
}

ClipNode::ClipNode(ClipNode&& moved) noexcept : ContainerNode(std::move(moved)) {}

ClipNode::~ClipNode() = default;

OpacityNodeHACK::OpacityNodeHACK(Session* session) : ContainerNode(session) {
  session->Enqueue(NewCreateOpacityNodeCmdHACK(id()));
}

OpacityNodeHACK::OpacityNodeHACK(OpacityNodeHACK&& moved) noexcept
    : ContainerNode(std::move(moved)) {}

OpacityNodeHACK::~OpacityNodeHACK() = default;

void OpacityNodeHACK::SetOpacity(float opacity) {
  opacity = clamp(opacity, 0.f, 1.f);
  session()->Enqueue(NewSetOpacityCmd(id(), opacity));
}

Variable::Variable(Session* session, fuchsia::ui::gfx::Value initial_value) : Resource(session) {
  session->Enqueue(NewCreateVariableCmd(id(), std::move(initial_value)));
}

Variable::Variable(Variable&& moved) noexcept : Resource(std::move(moved)) {}

Variable::~Variable() = default;

Scene::Scene(Session* session) : ContainerNode(session) {
  session->Enqueue(NewCreateSceneCmd(id()));
}

Scene::Scene(Scene&& moved) noexcept : ContainerNode(std::move(moved)) {}

Scene::~Scene() = default;

void Scene::AddLight(uint32_t light_id) { session()->Enqueue(NewAddLightCmd(id(), light_id)); }

void Scene::AddAmbientLight(uint32_t light_id) {
  session()->Enqueue(NewSceneAddAmbientLightCmd(id(), light_id));
}

void Scene::AddDirectionalLight(uint32_t light_id) {
  session()->Enqueue(NewSceneAddDirectionalLightCmd(id(), light_id));
}

void Scene::AddPointLight(uint32_t light_id) {
  session()->Enqueue(NewSceneAddPointLightCmd(id(), light_id));
}

void Scene::DetachLights() { session()->Enqueue(NewDetachLightsCmd(id())); }

void CameraBase::SetTransform(const std::array<float, 3>& eye_position,
                              const std::array<float, 3>& eye_look_at,
                              const std::array<float, 3>& eye_up) {
  session()->Enqueue(NewSetCameraTransformCmd(id(), eye_position, eye_look_at, eye_up));
}

void CameraBase::SetClipSpaceTransform(float x, float y, float scale) {
  session()->Enqueue(NewSetCameraClipSpaceTransformCmd(id(), x, y, scale));
}

void CameraBase::SetPoseBuffer(const Buffer& buffer, uint32_t num_entries, int64_t base_time,
                               uint64_t time_interval) {
  session()->Enqueue(
      NewSetCameraPoseBufferCmd(id(), buffer.id(), num_entries, base_time, time_interval));
}

void CameraBase::SetPoseBuffer(const Buffer& buffer, uint32_t num_entries, zx::time base_time,
                               zx::duration time_interval) {
  SetPoseBuffer(buffer, num_entries, base_time.get(), time_interval.get());
}

Camera::Camera(const Scene& scene) : Camera(scene.session(), scene.id()) {}

Camera::Camera(Session* session, uint32_t scene_id) : CameraBase(session) {
  session->Enqueue(NewCreateCameraCmd(id(), scene_id));
}

Camera::Camera(Camera&& moved) noexcept : CameraBase(std::move(moved)) {}

Camera::~Camera() = default;

void Camera::SetProjection(const float fovy) {
  session()->Enqueue(NewSetCameraProjectionCmd(id(), fovy));
}

StereoCamera::StereoCamera(const Scene& scene) : StereoCamera(scene.session(), scene.id()) {}

StereoCamera::StereoCamera(Session* session, uint32_t scene_id) : CameraBase(session) {
  session->Enqueue(NewCreateStereoCameraCmd(id(), scene_id));
}

StereoCamera::StereoCamera(StereoCamera&& moved) noexcept : CameraBase(std::move(moved)) {}

StereoCamera::~StereoCamera() = default;

void StereoCamera::SetStereoProjection(const std::array<float, 4 * 4>& left_projection,
                                       const std::array<float, 4 * 4>& right_projection) {
  session()->Enqueue(NewSetStereoCameraProjectionCmd(id(), left_projection, right_projection));
}

Renderer::Renderer(Session* session) : Resource(session) {
  session->Enqueue(NewCreateRendererCmd(id()));
}

Renderer::Renderer(Renderer&& moved) noexcept : Resource(std::move(moved)) {}

Renderer::~Renderer() = default;

void Renderer::SetCamera(uint32_t camera_id) {
  session()->Enqueue(NewSetCameraCmd(id(), camera_id));
}

void Renderer::SetParam(fuchsia::ui::gfx::RendererParam param) {
  session()->Enqueue(NewSetRendererParamCmd(id(), std::move(param)));
}

void Renderer::SetShadowTechnique(fuchsia::ui::gfx::ShadowTechnique technique) {
  auto param = fuchsia::ui::gfx::RendererParam();
  param.set_shadow_technique(technique);
  SetParam(std::move(param));
}

void Renderer::SetDisableClipping(bool disable_clipping) {
  session()->Enqueue(NewSetDisableClippingCmd(id(), disable_clipping));
}

void Renderer::SetEnableDebugging(bool enable_debugging) {
  auto param = fuchsia::ui::gfx::RendererParam();
  param.set_enable_debugging(enable_debugging);
  SetParam(std::move(param));
}

Layer::Layer(Session* session) : Resource(session) { session->Enqueue(NewCreateLayerCmd(id())); }

Layer::Layer(Layer&& moved) noexcept : Resource(std::move(moved)) {}

Layer::~Layer() = default;

void Layer::SetRenderer(uint32_t renderer_id) {
  session()->Enqueue(NewSetRendererCmd(id(), renderer_id));
}

void Layer::SetSize(const std::array<float, 2>& size) {
  session()->Enqueue(NewSetSizeCmd(id(), size));
}

LayerStack::LayerStack(Session* session) : Resource(session) {
  session->Enqueue(NewCreateLayerStackCmd(id()));
}

LayerStack::LayerStack(LayerStack&& moved) noexcept : Resource(std::move(moved)) {}

LayerStack::~LayerStack() = default;

void LayerStack::AddLayer(uint32_t layer_id) { session()->Enqueue(NewAddLayerCmd(id(), layer_id)); }

void LayerStack::RemoveLayer(uint32_t layer_id) {
  session()->Enqueue(NewRemoveLayerCmd(id(), layer_id));
}

void LayerStack::RemoveAllLayers() { session()->Enqueue(NewRemoveAllLayersCmd(id())); }

DisplayCompositor::DisplayCompositor(Session* session) : Resource(session) {
  session->Enqueue(NewCreateDisplayCompositorCmd(id()));
}

DisplayCompositor::DisplayCompositor(DisplayCompositor&& moved) noexcept
    : Resource(std::move(moved)) {}

DisplayCompositor::~DisplayCompositor() = default;

void DisplayCompositor::SetLayerStack(uint32_t layer_stack_id) {
  session()->Enqueue(NewSetLayerStackCmd(id(), layer_stack_id));
}

void DisplayCompositor::SetColorConversion(const std::array<float, 3>& preoffsets,
                                           const std::array<float, 3 * 3>& matrix,
                                           const std::array<float, 3>& postoffsets) {
  session()->Enqueue(NewSetDisplayColorConversionCmdHACK(id(), preoffsets, matrix, postoffsets));
}

void DisplayCompositor::SetLayoutRotation(uint32_t rotation_degrees) {
  session()->Enqueue(NewSetDisplayRotationCmdHACK(id(), rotation_degrees));
}

Compositor::Compositor(Session* session) : Resource(session) {
  session->Enqueue(NewCreateCompositorCmd(id()));
}

Compositor::Compositor(Compositor&& moved) noexcept : Resource(std::move(moved)) {}

Compositor::~Compositor() = default;

void Compositor::SetLayerStack(uint32_t layer_stack_id) {
  session()->Enqueue(NewSetLayerStackCmd(id(), layer_stack_id));
}

void Compositor::SetLayoutRotation(uint32_t rotation_degrees) {
  session()->Enqueue(NewSetDisplayRotationCmdHACK(id(), rotation_degrees));
}

Light::Light(Session* session) : Resource(session) {}

Light::Light(Light&& moved) noexcept : Resource(std::move(moved)) {}

Light::~Light() = default;

void Light::SetColor(const std::array<float, 3>& rgb) {
  session()->Enqueue(NewSetLightColorCmd(id(), rgb));
}

void Light::SetColor(uint32_t variable_id) {
  session()->Enqueue(NewSetLightColorCmd(id(), variable_id));
}

void Light::Detach() { session()->Enqueue(NewDetachLightCmd(id())); }

AmbientLight::AmbientLight(Session* session) : Light(session) {
  session->Enqueue(NewCreateAmbientLightCmd(id()));
}

AmbientLight::AmbientLight(AmbientLight&& moved) noexcept : Light(std::move(moved)) {}

AmbientLight::~AmbientLight() = default;

DirectionalLight::DirectionalLight(Session* session) : Light(session) {
  session->Enqueue(NewCreateDirectionalLightCmd(id()));
}

DirectionalLight::DirectionalLight(DirectionalLight&& moved) noexcept : Light(std::move(moved)) {}

DirectionalLight::~DirectionalLight() = default;

void DirectionalLight::SetDirection(const std::array<float, 3>& direction) {
  session()->Enqueue(NewSetLightDirectionCmd(id(), direction));
}

void DirectionalLight::SetDirection(uint32_t variable_id) {
  session()->Enqueue(NewSetLightDirectionCmd(id(), variable_id));
}

PointLight::PointLight(Session* session) : Light(session) {
  session->Enqueue(NewCreatePointLightCmd(id()));
}

PointLight::PointLight(PointLight&& moved) noexcept : Light(std::move(moved)) {}

PointLight::~PointLight() = default;

void PointLight::SetPosition(const std::array<float, 3>& position) {
  session()->Enqueue(NewSetPointLightPositionCmd(id(), position));
}

void PointLight::SetPosition(uint32_t variable_id) {
  session()->Enqueue(NewSetPointLightPositionCmd(id(), variable_id));
}

void PointLight::SetFalloff(float falloff) {
  session()->Enqueue(NewSetPointLightFalloffCmd(id(), falloff));
}

}  // namespace scenic
