// Copyright (c) 2012 The Chromium 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 UI_GFX_GEOMETRY_INSETS_H_
#define UI_GFX_GEOMETRY_INSETS_H_

#include <string>

#include "base/numerics/clamped_math.h"
#include "ui/gfx/geometry/geometry_export.h"
#include "ui/gfx/geometry/insets_f.h"
#include "ui/gfx/geometry/size.h"

namespace gfx {

class Vector2d;

// Represents the widths of the four borders or margins of an unspecified
// rectangle. An Insets stores the thickness of the top, left, bottom and right
// edges, without storing the actual size and position of the rectangle itself.
//
// This can be used to represent a space within a rectangle, by "shrinking" the
// rectangle by the inset amount on all four sides. Alternatively, it can
// represent a border that has a different thickness on each side.
class GEOMETRY_EXPORT Insets {
 public:
  constexpr Insets() : top_(0), left_(0), bottom_(0), right_(0) {}
  constexpr explicit Insets(int all)
      : top_(all),
        left_(all),
        bottom_(GetClampedValue(all, all)),
        right_(GetClampedValue(all, all)) {}
  constexpr explicit Insets(int vertical, int horizontal)
      : top_(vertical),
        left_(horizontal),
        bottom_(GetClampedValue(vertical, vertical)),
        right_(GetClampedValue(horizontal, horizontal)) {}
  constexpr Insets(int top, int left, int bottom, int right)
      : top_(top),
        left_(left),
        bottom_(GetClampedValue(top, bottom)),
        right_(GetClampedValue(left, right)) {}

  constexpr int top() const { return top_; }
  constexpr int left() const { return left_; }
  constexpr int bottom() const { return bottom_; }
  constexpr int right() const { return right_; }

  // Returns the total width taken up by the insets, which is the sum of the
  // left and right insets.
  constexpr int width() const { return left_ + right_; }

  // Returns the total height taken up by the insets, which is the sum of the
  // top and bottom insets.
  constexpr int height() const { return top_ + bottom_; }

  // Returns the sum of the left and right insets as the width, the sum of the
  // top and bottom insets as the height.
  constexpr Size size() const { return Size(width(), height()); }

  // Returns true if the insets are empty.
  bool IsEmpty() const { return width() == 0 && height() == 0; }

  void set_top(int top) {
    top_ = top;
    bottom_ = GetClampedValue(top_, bottom_);
  }
  void set_left(int left) {
    left_ = left;
    right_ = GetClampedValue(left_, right_);
  }
  void set_bottom(int bottom) { bottom_ = GetClampedValue(top_, bottom); }
  void set_right(int right) { right_ = GetClampedValue(left_, right); }

  void Set(int top, int left, int bottom, int right) {
    top_ = top;
    left_ = left;
    bottom_ = GetClampedValue(top_, bottom);
    right_ = GetClampedValue(left_, right);
  }

  bool operator==(const Insets& insets) const {
    return top_ == insets.top_ && left_ == insets.left_ &&
           bottom_ == insets.bottom_ && right_ == insets.right_;
  }

  bool operator!=(const Insets& insets) const {
    return !(*this == insets);
  }

  void operator+=(const Insets& insets) {
    top_ = base::ClampAdd(top_, insets.top_);
    left_ = base::ClampAdd(left_, insets.left_);
    bottom_ = GetClampedValue(top_, base::ClampAdd(bottom_, insets.bottom_));
    right_ = GetClampedValue(left_, base::ClampAdd(right_, insets.right_));
  }

  void operator-=(const Insets& insets) {
    top_ = base::ClampSub(top_, insets.top_);
    left_ = base::ClampSub(left_, insets.left_);
    bottom_ = GetClampedValue(top_, base::ClampSub(bottom_, insets.bottom_));
    right_ = GetClampedValue(left_, base::ClampSub(right_, insets.right_));
  }

  Insets operator-() const {
    return Insets(-base::MakeClampedNum(top_), -base::MakeClampedNum(left_),
                  -base::MakeClampedNum(bottom_),
                  -base::MakeClampedNum(right_));
  }

  // Adjusts the vertical and horizontal dimensions by the values described in
  // |vector|. Offsetting insets before applying to a rectangle would be
  // equivalent to offseting the rectangle then applying the insets.
  Insets Offset(const gfx::Vector2d& vector) const;

  operator InsetsF() const {
    return InsetsF(static_cast<float>(top()), static_cast<float>(left()),
                   static_cast<float>(bottom()), static_cast<float>(right()));
  }

  // Returns a string representation of the insets.
  std::string ToString() const;

 private:
  int top_;
  int left_;
  int bottom_;
  int right_;

  // See ui/gfx/geometry/rect.h
  // Returns true iff a+b would overflow max int.
  static constexpr bool AddWouldOverflow(int a, int b) {
    // In this function, GCC tries to make optimizations that would only work if
    // max - a wouldn't overflow but it isn't smart enough to notice that a > 0.
    // So cast everything to unsigned to avoid this.  As it is guaranteed that
    // max - a and b are both already positive, the cast is a noop.
    //
    // This is intended to be: a > 0 && max - a < b
    return a > 0 && b > 0 &&
           static_cast<unsigned>(std::numeric_limits<int>::max() - a) <
               static_cast<unsigned>(b);
  }

  // Returns true iff a+b would underflow min int.
  static constexpr bool AddWouldUnderflow(int a, int b) {
    return a < 0 && b < 0 && std::numeric_limits<int>::min() - a > b;
  }

  // Clamp the right/bottom to avoid integer over/underflow in width() and
  // height(). This returns the right/bottom given a top_or_left and a
  // bottom_or_right.
  // TODO(enne): this should probably use base::ClampAdd, but that
  // function is not a constexpr.
  static constexpr int GetClampedValue(int top_or_left, int bottom_or_right) {
    if (AddWouldOverflow(top_or_left, bottom_or_right)) {
      return std::numeric_limits<int>::max() - top_or_left;
    } else if (AddWouldUnderflow(top_or_left, bottom_or_right)) {
      // If |top_or_left| and |bottom_or_right| are both negative,
      // adds |top_or_left| to prevent underflow by subtracting it.
      return std::numeric_limits<int>::min() - top_or_left;
    } else {
      return bottom_or_right;
    }
  }
};

// This is declared here for use in gtest-based unit tests but is defined in
// the //ui/gfx:test_support target. Depend on that to use this in your unit
// test. This should not be used in production code - call ToString() instead.
void PrintTo(const Insets& point, ::std::ostream* os);

inline Insets operator+(Insets lhs, const Insets& rhs) {
  lhs += rhs;
  return lhs;
}

inline Insets operator-(Insets lhs, const Insets& rhs) {
  lhs -= rhs;
  return lhs;
}

// Helper methods to scale a gfx::Insets to a new gfx::Insets.
GEOMETRY_EXPORT Insets ScaleToCeiledInsets(const Insets& insets,
                                           float x_scale,
                                           float y_scale);
GEOMETRY_EXPORT Insets ScaleToCeiledInsets(const Insets& insets, float scale);
GEOMETRY_EXPORT Insets ScaleToFlooredInsets(const Insets& insets,
                                            float x_scale,
                                            float y_scale);
GEOMETRY_EXPORT Insets ScaleToFlooredInsets(const Insets& insets, float scale);
GEOMETRY_EXPORT Insets ScaleToRoundedInsets(const Insets& insets,
                                            float x_scale,
                                            float y_scale);
GEOMETRY_EXPORT Insets ScaleToRoundedInsets(const Insets& insets, float scale);

}  // namespace gfx

#endif  // UI_GFX_GEOMETRY_INSETS_H_
