// Copyright 2016 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef COBALT_CSSOM_MAP_TO_MESH_FUNCTION_H_
#define COBALT_CSSOM_MAP_TO_MESH_FUNCTION_H_

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "cobalt/base/polymorphic_equatable.h"
#include "cobalt/cssom/filter_function.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/cssom/property_value.h"
#include "cobalt/cssom/url_value.h"
#include "third_party/glm/glm/mat4x4.hpp"

namespace cobalt {
namespace cssom {

// Represent a map-to-mesh filter.
class MapToMeshFunction : public FilterFunction {
 public:
  // A resolution-matched mesh specifier.
  class ResolutionMatchedMesh {
   public:
    ResolutionMatchedMesh(int width_match, int height_match,
                          const scoped_refptr<PropertyValue>& mesh_url);
    int width_match() const { return width_match_; }
    int height_match() const { return height_match_; }
    const scoped_refptr<PropertyValue>& mesh_url() const { return mesh_url_; }
    bool operator==(const MapToMeshFunction::ResolutionMatchedMesh& rhs) const;
    bool operator!=(const MapToMeshFunction::ResolutionMatchedMesh& rhs) const;

   private:
    const int width_match_;
    const int height_match_;
    const scoped_refptr<PropertyValue> mesh_url_;
  };

  // Type of the source of the mesh: either a built-in mesh type or a custom
  // mesh.
  enum MeshSpecType {
    // Built-in rectangular mesh.
    kRectangular,
    // Built-in equirectangular mesh.
    kEquirectangular,
    // List of custom binary mesh URLs.
    kUrls
  };
  typedef std::vector<std::unique_ptr<ResolutionMatchedMesh>>
      ResolutionMatchedMeshListBuilder;

  // Contains the specification of the mesh source.
  class MeshSpec {
   public:
    explicit MeshSpec(MeshSpecType mesh_type) : mesh_type_(mesh_type) {
      // Check that this is a built-in mesh type.
      DCHECK(mesh_type == kRectangular || mesh_type == kEquirectangular);
    }

    MeshSpec(MeshSpecType mesh_type,
             const scoped_refptr<PropertyValue>& mesh_url,
             ResolutionMatchedMeshListBuilder resolution_matched_meshes)
        : mesh_type_(mesh_type),
          mesh_url_(mesh_url),
          resolution_matched_meshes_(std::move(resolution_matched_meshes)) {
      DCHECK_EQ(mesh_type_, kUrls);
      DCHECK(mesh_url);
    }

    const scoped_refptr<PropertyValue>& mesh_url() const {
      DCHECK_EQ(mesh_type_, kUrls);
      return mesh_url_;
    }
    const ResolutionMatchedMeshListBuilder& resolution_matched_meshes() const {
      DCHECK_EQ(mesh_type_, kUrls);
      return resolution_matched_meshes_;
    }
    MeshSpecType mesh_type() const { return mesh_type_; }

   private:
    MeshSpecType mesh_type_;
    scoped_refptr<PropertyValue> mesh_url_;
    ResolutionMatchedMeshListBuilder resolution_matched_meshes_;

    DISALLOW_COPY_AND_ASSIGN(MeshSpec);
  };

  MapToMeshFunction(std::unique_ptr<MeshSpec> mesh_spec,
                    float horizontal_fov_in_radians,
                    float vertical_fov_in_radians, const glm::mat4& transform,
                    const scoped_refptr<KeywordValue>& stereo_mode)
      : mesh_spec_(std::move(mesh_spec)),
        horizontal_fov_in_radians_(horizontal_fov_in_radians),
        vertical_fov_in_radians_(vertical_fov_in_radians),
        transform_(transform),
        stereo_mode_(stereo_mode) {
    DCHECK(mesh_spec_);
    DCHECK_NE(mesh_spec_->mesh_type(), kRectangular);
    DCHECK(stereo_mode_);
  }

  // Alternate constructor for mesh URL lists.
  MapToMeshFunction(const scoped_refptr<PropertyValue>& mesh_url,
                    ResolutionMatchedMeshListBuilder resolution_matched_meshes,
                    float horizontal_fov_in_radians,
                    float vertical_fov_in_radians, const glm::mat4& transform,
                    const scoped_refptr<KeywordValue>& stereo_mode)
      : mesh_spec_(new MeshSpec(kUrls, mesh_url,
                                std::move(resolution_matched_meshes))),
        horizontal_fov_in_radians_(horizontal_fov_in_radians),
        vertical_fov_in_radians_(vertical_fov_in_radians),
        transform_(transform),
        stereo_mode_(stereo_mode) {
    DCHECK(stereo_mode_);
  }

  // Alternate constructor for built-in meshes.
  MapToMeshFunction(MeshSpecType spec_type, float horizontal_fov_in_radians,
                    float vertical_fov_in_radians, const glm::mat4& transform,
                    const scoped_refptr<KeywordValue>& stereo_mode)
      : mesh_spec_(new MeshSpec(spec_type)),
        horizontal_fov_in_radians_(horizontal_fov_in_radians),
        vertical_fov_in_radians_(vertical_fov_in_radians),
        transform_(transform),
        stereo_mode_(stereo_mode) {
    DCHECK_NE(spec_type, kRectangular);
    DCHECK(stereo_mode_);
  }

  // Alternate constructor for built-in meshes without FOV or transforms.
  MapToMeshFunction(MeshSpecType spec_type,
                    const scoped_refptr<KeywordValue>& stereo_mode)
      : mesh_spec_(new MeshSpec(spec_type)),
        horizontal_fov_in_radians_(0.0f),
        vertical_fov_in_radians_(0.0f),
        transform_(glm::mat4()),
        stereo_mode_(stereo_mode) {
    DCHECK_EQ(spec_type, kRectangular);
    DCHECK(stereo_mode_);
  }

  ~MapToMeshFunction() override {}

  const MeshSpec& mesh_spec() const { return *mesh_spec_; }
  float horizontal_fov_in_radians() const { return horizontal_fov_in_radians_; }
  float vertical_fov_in_radians() const { return vertical_fov_in_radians_; }
  const glm::mat4& transform() const { return transform_; }
  const scoped_refptr<KeywordValue>& stereo_mode() const {
    return stereo_mode_;
  }

  std::string ToString() const override;

  bool operator==(const MapToMeshFunction& rhs) const;

  static const MapToMeshFunction* ExtractFromFilterList(
      PropertyValue* filter_list);

  DEFINE_POLYMORPHIC_EQUATABLE_TYPE(MapToMeshFunction);

 private:
  const std::unique_ptr<MeshSpec> mesh_spec_;
  const float horizontal_fov_in_radians_;
  const float vertical_fov_in_radians_;
  const glm::mat4 transform_;
  const scoped_refptr<KeywordValue> stereo_mode_;

  DISALLOW_COPY_AND_ASSIGN(MapToMeshFunction);
};

}  // namespace cssom
}  // namespace cobalt

#endif  // COBALT_CSSOM_MAP_TO_MESH_FUNCTION_H_
