// Copyright 2014 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_LAYOUT_USED_STYLE_H_
#define COBALT_LAYOUT_USED_STYLE_H_

#include "cobalt/cssom/css_computed_style_data.h"
#include "cobalt/cssom/linear_gradient_value.h"
#include "cobalt/cssom/property_list_value.h"
#include "cobalt/cssom/property_value.h"
#include "cobalt/cssom/property_value_visitor.h"
#include "cobalt/cssom/radial_gradient_value.h"
#include "cobalt/cssom/transform_function_list_value.h"
#include "cobalt/cssom/transform_matrix.h"
#include "cobalt/dom/font_cache.h"
#include "cobalt/dom/font_list.h"
#include "cobalt/dom/html_element_context.h"
#include "cobalt/layout/layout_unit.h"
#include "cobalt/layout/size_layout_unit.h"
#include "cobalt/loader/image/animated_image_tracker.h"
#include "cobalt/loader/image/image.h"
#include "cobalt/loader/image/image_cache.h"
#include "cobalt/loader/mesh/mesh_projection.h"
#include "cobalt/math/size.h"
#include "cobalt/math/size_f.h"
#include "cobalt/render_tree/color_rgba.h"
#include "cobalt/render_tree/node.h"
#include "cobalt/render_tree/resource_provider.h"
#include "cobalt/render_tree/rounded_corners.h"

namespace cobalt {
namespace layout {

// The used value is the result of taking the computed value and completing any
// remaining calculations to make it the absolute theoretical value used in
// the layout of the document. If the property does not apply to this element,
// then the element has no used value for that property.
//   https://www.w3.org/TR/css-cascade-3/#used

// All used values are expressed in terms of render tree.
//
// This file contains facilities to convert CSSOM values to render tree values
// for properties not affected by the layout, such as "color" or "font-size",
// as for them the used values are the same as the computed values.

class ContainingBlock;

class UsedStyleProvider {
 public:
  // A function that will attach a camera matrix projection transform to a given
  // sub render tree.  |max_horizontal_fov_rad| and |max_vertical_fov_rad|
  // dictate the minimum field of view to use in that direction, in radians.
  // These minimum FOV values are compared against the values derived from
  // applying the aspect ratio to the other FOV value, and using whichever one
  // is most minimum.
  typedef base::Callback<scoped_refptr<render_tree::Node>(
      const scoped_refptr<render_tree::Node>&, float max_horizontal_fov_rad,
      float max_vertical_fov_rad)> AttachCameraNodeFunction;

  UsedStyleProvider(dom::HTMLElementContext* html_element_context,
                    dom::FontCache* font_cache,
                    const AttachCameraNodeFunction& attach_camera_node_function,
                    bool enable_image_animations);

  scoped_refptr<dom::FontList> GetUsedFontList(
      const scoped_refptr<cssom::PropertyValue>& font_family_refptr,
      const scoped_refptr<cssom::PropertyValue>& font_size_refptr,
      const scoped_refptr<cssom::PropertyValue>& font_style_refptr,
      const scoped_refptr<cssom::PropertyValue>& font_weight_refptr);

  scoped_refptr<loader::image::Image> ResolveURLToImage(const GURL& url);
  scoped_refptr<loader::mesh::MeshProjection> ResolveURLToMeshProjection(
      const GURL& url);

  const AttachCameraNodeFunction attach_camera_node_function() const {
    return attach_camera_node_function_;
  }

  // Notifies animated image tracker to update the playing status of animated
  // images.
  void UpdateAnimatedImages();

  bool enable_image_animations() const { return enable_image_animations_; }

 private:
  // Called after layout is completed so that it can perform any necessary
  // cleanup. Its primary current purpose is making a request to the font cache
  // to remove any font lists that are no longer being referenced by boxes.
  void CleanupAfterLayout();

  dom::FontCache* const font_cache_;
  loader::image::AnimatedImageTracker* const animated_image_tracker_;
  loader::image::ImageCache* const image_cache_;
  loader::mesh::MeshCache* const mesh_cache_;
  AttachCameraNodeFunction attach_camera_node_function_;

  // |font_list_key_| is retained in between lookups so that the font names
  // vector will not need to allocate elements each time that it is populated.
  dom::FontListKey font_list_key_;

  // The last_font member variables are used to speed up |GetUsedFontList()|.
  // Around 85% of the time in current clients, the current font list matches
  // the last font list, so immediately comparing the current font list's
  // properties against the last font list's properties, prior to updating the
  // font list key and performing a font cache lookup, results in a significant
  // performance improvement.
  scoped_refptr<cssom::PropertyValue> last_font_family_refptr_;
  scoped_refptr<cssom::PropertyValue> last_font_style_refptr_;
  scoped_refptr<cssom::PropertyValue> last_font_weight_refptr_;
  scoped_refptr<dom::FontList> last_font_list_;

  // If true, animated WebP images should animate, otherwise they should not.
  const bool enable_image_animations_;

  friend class UsedStyleProviderLayoutScope;
  DISALLOW_COPY_AND_ASSIGN(UsedStyleProvider);
};

class UsedStyleProviderLayoutScope {
 public:
  explicit UsedStyleProviderLayoutScope(UsedStyleProvider* used_style_provider);
  ~UsedStyleProviderLayoutScope();

 private:
  UsedStyleProvider* const used_style_provider_;
};

render_tree::ColorRGBA GetUsedColor(
    const scoped_refptr<cssom::PropertyValue>& color_refptr);

LayoutUnit GetUsedLength(
    const scoped_refptr<cssom::PropertyValue>& length_refptr);

LayoutUnit GetUsedNonNegativeLength(
    const scoped_refptr<cssom::PropertyValue>& length_refptr);

class UsedBackgroundNodeProvider
    : public cssom::NotReachedPropertyValueVisitor {
 public:
  UsedBackgroundNodeProvider(
      const math::RectF& frame,
      const scoped_refptr<cssom::PropertyValue>& background_size,
      const scoped_refptr<cssom::PropertyValue>& background_position,
      const scoped_refptr<cssom::PropertyValue>& background_repeat,
      UsedStyleProvider* used_style_provider);

  void VisitAbsoluteURL(cssom::AbsoluteURLValue* url_value) OVERRIDE;
  void VisitLinearGradient(
      cssom::LinearGradientValue* linear_gradient_value) OVERRIDE;
  void VisitRadialGradient(
      cssom::RadialGradientValue* radial_gradient_value) OVERRIDE;

  scoped_refptr<render_tree::Node> background_node() {
    return background_node_;
  }

  bool is_opaque() const { return is_opaque_; }

 private:
  const math::RectF frame_;
  const scoped_refptr<cssom::PropertyValue> background_size_;
  const scoped_refptr<cssom::PropertyValue> background_position_;
  const scoped_refptr<cssom::PropertyValue> background_repeat_;
  UsedStyleProvider* const used_style_provider_;

  scoped_refptr<render_tree::Node> background_node_;

  bool is_opaque_;

  DISALLOW_COPY_AND_ASSIGN(UsedBackgroundNodeProvider);
};

class UsedBackgroundPositionProvider
    : public cssom::NotReachedPropertyValueVisitor {
 public:
  UsedBackgroundPositionProvider(const math::SizeF& frame_size,
                                 const math::SizeF& image_actual_size);

  void VisitPropertyList(
      cssom::PropertyListValue* property_list_value) OVERRIDE;

  float translate_x() { return translate_x_; }
  float translate_y() { return translate_y_; }

  float translate_x_relative_to_frame() {
    return frame_size_.width() == 0.0f ? 0.0f
                                       : translate_x_ / frame_size_.width();
  }
  float translate_y_relative_to_frame() {
    return frame_size_.height() == 0.0f ? 0.0f
                                        : translate_y_ / frame_size_.height();
  }

 private:
  const math::SizeF frame_size_;
  const math::SizeF image_actual_size_;

  float translate_x_;
  float translate_y_;

  DISALLOW_COPY_AND_ASSIGN(UsedBackgroundPositionProvider);
};

class UsedBackgroundRepeatProvider
    : public cssom::NotReachedPropertyValueVisitor {
 public:
  UsedBackgroundRepeatProvider();

  void VisitPropertyList(
      cssom::PropertyListValue* property_list_value) OVERRIDE;

  bool repeat_x() { return repeat_x_; }
  bool repeat_y() { return repeat_y_; }

 private:
  bool repeat_x_;
  bool repeat_y_;

  DISALLOW_COPY_AND_ASSIGN(UsedBackgroundRepeatProvider);
};

class UsedBackgroundSizeProvider
    : public cssom::NotReachedPropertyValueVisitor {
 public:
  UsedBackgroundSizeProvider(const math::SizeF& frame_size,
                             const math::Size& image_size);

  void VisitPropertyList(
      cssom::PropertyListValue* property_list_value) OVERRIDE;
  void VisitKeyword(cssom::KeywordValue* keyword) OVERRIDE;

  float width_scale_relative_to_frame() const {
    return frame_size_.width() == 0.0f ? 0.0f : width_ / frame_size_.width();
  }
  float height_scale_relative_to_frame() const {
    return frame_size_.height() == 0.0f ? 0.0f : height_ / frame_size_.height();
  }

  float width() const { return width_; }
  float height() const { return height_; }

 private:
  void ConvertWidthAndHeightScale(float width_scale, float height_scale);

  const math::SizeF frame_size_;
  const math::Size image_size_;

  float width_;
  float height_;

  DISALLOW_COPY_AND_ASSIGN(UsedBackgroundSizeProvider);
};

class UsedBorderRadiusProvider : public cssom::NotReachedPropertyValueVisitor {
 public:
  explicit UsedBorderRadiusProvider(const math::SizeF& frame_size);

  void VisitLength(cssom::LengthValue* length) OVERRIDE;
  void VisitPercentage(cssom::PercentageValue* percentage) OVERRIDE;

  const base::optional<render_tree::RoundedCorner>& rounded_corner() const {
    return rounded_corner_;
  }

 private:
  base::optional<render_tree::RoundedCorner> rounded_corner_;

  const math::SizeF frame_size_;

  DISALLOW_COPY_AND_ASSIGN(UsedBorderRadiusProvider);
};

class UsedLineHeightProvider : public cssom::NotReachedPropertyValueVisitor {
 public:
  explicit UsedLineHeightProvider(
      const render_tree::FontMetrics& font_metrics,
      const scoped_refptr<cssom::PropertyValue>& font_size);

  void VisitKeyword(cssom::KeywordValue* keyword) OVERRIDE;
  void VisitLength(cssom::LengthValue* length) OVERRIDE;
  void VisitNumber(cssom::NumberValue* length) OVERRIDE;

  LayoutUnit used_line_height() const { return used_line_height_; }
  LayoutUnit half_leading() const { return half_leading_; }

  // Half the leading is added above ascent (A) and the other half below
  // descent (D), giving the glyph and its leading (L) a total height above
  // the baseline of A' = A + L/2 and a total depth of D' = D + L/2.
  //   https://www.w3.org/TR/CSS21/visudet.html#leading
  LayoutUnit baseline_offset_from_top() const {
    return LayoutUnit(LayoutUnit(font_metrics_.ascent()) + half_leading_);
  }
  LayoutUnit baseline_offset_from_bottom() const {
    return LayoutUnit(LayoutUnit(font_metrics_.descent()) + half_leading_);
  }

 private:
  void UpdateHalfLeading();

  const render_tree::FontMetrics font_metrics_;
  const scoped_refptr<cssom::PropertyValue> font_size_;

  LayoutUnit used_line_height_;
  LayoutUnit half_leading_;

  DISALLOW_COPY_AND_ASSIGN(UsedLineHeightProvider);
};

math::Vector2dF GetTransformOrigin(const math::RectF& used_rect,
                                   cssom::PropertyValue* value);

cssom::TransformMatrix GetTransformMatrix(cssom::PropertyValue* value);

// Functions to calculate used values of box model properties.
base::optional<LayoutUnit> GetUsedLeftIfNotAuto(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size);
base::optional<LayoutUnit> GetUsedTopIfNotAuto(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size);
base::optional<LayoutUnit> GetUsedRightIfNotAuto(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size);
base::optional<LayoutUnit> GetUsedBottomIfNotAuto(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size);
base::optional<LayoutUnit> GetUsedWidthIfNotAuto(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size,
    bool* width_depends_on_containing_block);
base::optional<LayoutUnit> GetUsedMaxHeightIfNotNone(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size,
    bool* height_depends_on_containing_block);
base::optional<LayoutUnit> GetUsedMaxWidthIfNotNone(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size,
    bool* width_depends_on_containing_block);
LayoutUnit GetUsedMinHeight(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size,
    bool* height_depends_on_containing_block);
LayoutUnit GetUsedMinWidth(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size,
    bool* width_depends_on_containing_block);
base::optional<LayoutUnit> GetUsedHeightIfNotAuto(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size);
base::optional<LayoutUnit> GetUsedMarginLeftIfNotAuto(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size);
base::optional<LayoutUnit> GetUsedMarginTopIfNotAuto(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size);
base::optional<LayoutUnit> GetUsedMarginRightIfNotAuto(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size);
base::optional<LayoutUnit> GetUsedMarginBottomIfNotAuto(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size);
LayoutUnit GetUsedBorderLeft(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style);
LayoutUnit GetUsedBorderTop(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style);
LayoutUnit GetUsedBorderRight(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style);
LayoutUnit GetUsedBorderBottom(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style);
LayoutUnit GetUsedPaddingLeft(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size);
LayoutUnit GetUsedPaddingTop(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size);
LayoutUnit GetUsedPaddingRight(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size);
LayoutUnit GetUsedPaddingBottom(
    const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style,
    const SizeLayoutUnit& containing_block_size);

}  // namespace layout
}  // namespace cobalt

#endif  // COBALT_LAYOUT_USED_STYLE_H_
