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

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.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 ScopedVector<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_(resolution_matched_meshes.Pass()) {
      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(scoped_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_(mesh_spec.Pass()),
        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, resolution_matched_meshes.Pass())),
        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 scoped_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_
