// Copyright 2016 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.

#ifndef SRC_UI_LIB_ESCHER_SCENE_OBJECT_H_
#define SRC_UI_LIB_ESCHER_SCENE_OBJECT_H_

#include <unordered_map>

#include "src/ui/lib/escher/geometry/transform.h"
#include "src/ui/lib/escher/material/material.h"
#include "src/ui/lib/escher/scene/shape.h"

namespace escher {

// An object instance to be drawn using a shape and a material.
// Does not retain ownership of the material.
class Object {
 public:
  // Constructors.
  Object(const Transform& transform, MeshPtr mesh, MaterialPtr material);
  Object(const mat4& transform, MeshPtr mesh, MaterialPtr material);
  Object(const vec3& position, MeshPtr mesh, MaterialPtr material);
  Object(std::vector<Object> clippers, std::vector<Object> clippees);
  Object(const Object& other) = default;
  Object(Object&& other) = default;
  static Object NewRect(const vec2& top_left_position, const vec2& size, float z,
                        MaterialPtr material);
  static Object NewRect(const vec3& top_left_position, const vec2& size, MaterialPtr material);
  static Object NewRect(const Transform& transform, MaterialPtr material);
  static Object NewRect(const mat4& transform, MaterialPtr material);
  static Object NewCircle(const vec2& center_position, float radius, float z, MaterialPtr material);
  static Object NewCircle(const vec3& center_position, float radius, MaterialPtr material);
  static Object NewCircle(const mat4& transform, float radius, MaterialPtr material);

  // Return the object's 4x4 transformation matrix.
  const mat4& transform() const { return transform_; }

  // The shape to draw.
  const Shape& shape() const { return shape_; }
  Shape& mutable_shape() { return shape_; }

  // The material with which to fill the shape.
  const MaterialPtr& material() const { return material_; }
  void set_material(MaterialPtr material) { material_ = std::move(material); }

  // Return the bounding box that encompasses the object's shape, as well as
  // all of its clippers (but not clippees, since their clipped bounds are
  // by definition within the clippers' bounds).
  BoundingBox bounding_box() const;

  Object& set_shape_modifiers(ShapeModifiers modifiers) {
    shape_.set_modifiers(modifiers);
    return *this;
  }

  // Obtain a temporary reference to data corresponding to a particular
  // ShapeModifier; the modifier that is used is determined by DataT::kType.
  // The returned pointer is invalidated by the next call to
  // set_shape_modifier_data().  Escher clients should only use pre-existing
  // Escher types for DataT (e.g. ModifierWobble), since those are the ones that
  // the renderer implementation knows how to deal with.
  template <typename DataT>
  const DataT* shape_modifier_data() const;
  // Set per-object ShapeModifier data for the ShapeModifier type specified by
  // DataT::kType.  Uses memcpy() to copy the DataT into shape_modifier_data_.
  template <typename DataT>
  void set_shape_modifier_data(const DataT& data);
  // Remove both the shape modifier data and the flag from the shape.
  template <typename DataT>
  void remove_shape_modifier();

  // Return the list of objects whose shapes will be used to clip 'clippees()'.
  // It is OK for these objects to not have a material; in this case the objects
  // update the stencil buffer, but not the color/depth buffers.
  const std::vector<Object>& clippers() const { return clippers_; }

  // Return the list of objects whose shapes will be clipped by 'clippers()'.
  const std::vector<Object>& clippees() const { return clippees_; }

 private:
  Object(mat4 transform, Shape shape, MaterialPtr material)
      : transform_(transform), shape_(std::move(shape)), material_(std::move(material)) {}

  mat4 transform_;
  Shape shape_;
  MaterialPtr material_;
  std::unordered_map<ShapeModifier, std::vector<uint8_t>> shape_modifier_data_;
  std::vector<Object> clippers_;
  std::vector<Object> clippees_;
};

// Inline function definitions.

template <typename DataT>
const DataT* Object::shape_modifier_data() const {
  auto it = shape_modifier_data_.find(DataT::kType);
  if (it == shape_modifier_data_.end()) {
    return nullptr;
  } else {
    FXL_DCHECK(it->second.size() == sizeof(DataT));
    return reinterpret_cast<const DataT*>(it->second.data());
  }
}

template <typename DataT>
void Object::set_shape_modifier_data(const DataT& data) {
  auto& vect = shape_modifier_data_[DataT::kType];
  vect.resize(sizeof(DataT));
  memcpy(vect.data(), &data, sizeof(DataT));
}

template <typename DataT>
void Object::remove_shape_modifier() {
  shape_modifier_data_.erase(DataT::kType);
  shape_.remove_modifier(DataT::kType);
}

template <typename DataT>
void set_shape_modifier_data(const DataT& data);

}  // namespace escher

#endif  // SRC_UI_LIB_ESCHER_SCENE_OBJECT_H_
