// 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_RENDER_TREE_ROUNDED_CORNERS_H_
#define COBALT_RENDER_TREE_ROUNDED_CORNERS_H_

#include <algorithm>

#include "cobalt/math/insets_f.h"
#include "cobalt/math/rect_f.h"

namespace cobalt {
namespace render_tree {

// RoundedCorner represents one of the corners of an rectangle. It contains the
// lengths of the semi-major axis and the semi-minor axis of an ellipse.
struct RoundedCorner {
  RoundedCorner() : horizontal(0.0f), vertical(0.0f) {}

  RoundedCorner(float horizontal, float vertical)
      : horizontal(horizontal), vertical(vertical) {}

  //  If either length is zero, the corner is square, not rounded.
  bool IsSquare() const { return horizontal == 0.0f || vertical == 0.0f; }

  RoundedCorner Inset(float x, float y) const {
    return RoundedCorner(std::max(0.0f, horizontal - x),
                         std::max(0.0f, vertical - y));
  }

  bool operator==(const RoundedCorner& other) const {
    return horizontal == other.horizontal && vertical == other.vertical;
  }
  bool operator>=(const RoundedCorner& other) const {
    return horizontal >= other.horizontal && vertical >= other.vertical;
  }

  // |horizontal| and |vertial| represent the horizontal radius and vertical
  // radius of a corner.
  float horizontal;
  float vertical;
};

// RoundedCorners represents 4 rounded corners of an rectangle. Top left, top
// right, bottom right and bottom left.
struct RoundedCorners {
  explicit RoundedCorners(const RoundedCorner& corner)
      : top_left(corner),
        top_right(corner),
        bottom_right(corner),
        bottom_left(corner) {}

  RoundedCorners(float horizontal, float vertical)
      : top_left(horizontal, vertical),
        top_right(horizontal, vertical),
        bottom_right(horizontal, vertical),
        bottom_left(horizontal, vertical) {}

  RoundedCorners(const RoundedCorners& radiuses)
      : top_left(radiuses.top_left),
        top_right(radiuses.top_right),
        bottom_right(radiuses.bottom_right),
        bottom_left(radiuses.bottom_left) {}

  RoundedCorners(const RoundedCorner& top_left, const RoundedCorner& top_right,
                 const RoundedCorner& bottom_right,
                 const RoundedCorner& bottom_left)
      : top_left(top_left),
        top_right(top_right),
        bottom_right(bottom_right),
        bottom_left(bottom_left) {}

  bool operator==(const RoundedCorners& other) const {
    return top_left == other.top_left && top_right == other.top_right &&
           bottom_right == other.bottom_right &&
           bottom_left == other.bottom_left;
  }

  RoundedCorners Inset(float left, float top, float right, float bottom) const {
    return RoundedCorners(
        top_left.Inset(left, top), top_right.Inset(right, top),
        bottom_right.Inset(right, bottom), bottom_left.Inset(left, bottom));
  }

  RoundedCorners Inset(const math::InsetsF& insets) const {
    return Inset(insets.left(), insets.top(), insets.right(), insets.bottom());
  }

  RoundedCorners Scale(float sx, float sy) const;

  // Ensure the rounded corners' radii do not exceed the length of the
  // corresponding edge of the given rect.
  RoundedCorners Normalize(const math::RectF& rect) const;
  bool IsNormalized(const math::RectF& rect) const;

  bool AreSquares() const {
    return top_left.IsSquare() && top_right.IsSquare() &&
           bottom_right.IsSquare() && bottom_left.IsSquare();
  }

  // Returns true if all corners have the same value as the input.
  bool AllCornersEqual(const RoundedCorner& rhs) const {
    return top_left == rhs && top_right == rhs && bottom_right == rhs &&
           bottom_left == rhs;
  }

  // Returns true if all corners' radii are greater than or equal to the
  // corresponding radii of the input.
  bool AllCornersGE(const RoundedCorner& rhs) const {
    return top_left >= rhs && top_right >= rhs && bottom_right >= rhs &&
           bottom_left >= rhs;
  }

  RoundedCorner top_left;
  RoundedCorner top_right;
  RoundedCorner bottom_right;
  RoundedCorner bottom_left;
};

}  // namespace render_tree
}  // namespace cobalt

#endif  // COBALT_RENDER_TREE_ROUNDED_CORNERS_H_
