// 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::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
