// Copyright 2018 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.

#include "ui/gfx/geometry/rrect_f.h"

#include <iomanip>
#include <iostream>
#include <sstream>

#include "base/values.h"
#include "third_party/skia/include/core/SkMatrix.h"

namespace gfx {

// Sets all x radii to x_rad, and all y radii to y_rad. If one of x_rad or
// y_rad are zero, sets ALL radii to zero.
RRectF::RRectF(float x,
               float y,
               float width,
               float height,
               float x_rad,
               float y_rad)
    : skrrect_(SkRRect::MakeRectXY(SkRect::MakeXYWH(x, y, width, height),
                                   x_rad,
                                   y_rad)) {
  if (IsEmpty()) {
    // Make sure that empty rects are created fully empty, not with some
    // non-zero dimensions.
    skrrect_ = SkRRect::MakeEmpty();
  }
}

// Directly sets all four corners.
RRectF::RRectF(float x,
               float y,
               float width,
               float height,
               float upper_left_x,
               float upper_left_y,
               float upper_right_x,
               float upper_right_y,
               float lower_right_x,
               float lower_right_y,
               float lower_left_x,
               float lower_left_y) {
  SkVector radii[4] = {
      {upper_left_x, upper_left_y},
      {upper_right_x, upper_right_y},
      {lower_right_x, lower_right_y},
      {lower_left_x, lower_left_y},
  };
  skrrect_.setRectRadii(SkRect::MakeXYWH(x, y, width, height), radii);
  if (IsEmpty()) {
    // Make sure that empty rects are created fully empty, not with some
    // non-zero dimensions.
    skrrect_ = SkRRect::MakeEmpty();
  }
}

gfx::Vector2dF RRectF::GetSimpleRadii() const {
  DCHECK(GetType() <= Type::kOval);
  SkPoint result = skrrect_.getSimpleRadii();
  return gfx::Vector2dF(result.x(), result.y());
}

float RRectF::GetSimpleRadius() const {
  DCHECK(GetType() <= Type::kOval);
  SkPoint result = skrrect_.getSimpleRadii();
  DCHECK_EQ(result.x(), result.y());
  return result.x();
}

RRectF::Type RRectF::GetType() const {
  SkPoint rad;
  switch (skrrect_.getType()) {
    case SkRRect::kEmpty_Type:
      return Type::kEmpty;
    case SkRRect::kRect_Type:
      return Type::kRect;
    case SkRRect::kSimple_Type:
      rad = skrrect_.getSimpleRadii();
      if (rad.x() == rad.y()) {
        return Type::kSingle;
      }
      return Type::kSimple;
    case SkRRect::kOval_Type:
      rad = skrrect_.getSimpleRadii();
      if (rad.x() == rad.y()) {
        return Type::kSingle;
      }
      return Type::kOval;
    case SkRRect::kNinePatch_Type:
    case SkRRect::kComplex_Type:
    default:
      return Type::kComplex;
  }
}

gfx::Vector2dF RRectF::GetCornerRadii(Corner corner) const {
  SkPoint result = skrrect_.radii(SkRRect::Corner(corner));
  return gfx::Vector2dF(result.x(), result.y());
}

void RRectF::GetAllRadii(SkVector radii[4]) const {
  // Unfortunately, the only way to get all radii is one at a time.
  radii[SkRRect::kUpperLeft_Corner] =
      skrrect_.radii(SkRRect::kUpperLeft_Corner);
  radii[SkRRect::kUpperRight_Corner] =
      skrrect_.radii(SkRRect::kUpperRight_Corner);
  radii[SkRRect::kLowerRight_Corner] =
      skrrect_.radii(SkRRect::kLowerRight_Corner);
  radii[SkRRect::kLowerLeft_Corner] =
      skrrect_.radii(SkRRect::kLowerLeft_Corner);
}

void RRectF::SetCornerRadii(Corner corner, float x_rad, float y_rad) {
  // Unfortunately, the only way to set this is to create a new SkRRect.
  SkVector radii[4];
  GetAllRadii(radii);
  radii[SkRRect::Corner(corner)] = SkPoint::Make(x_rad, y_rad);
  skrrect_.setRectRadii(skrrect_.rect(), radii);
}

void RRectF::Scale(float x_scale, float y_scale) {
  if (IsEmpty()) {
    // SkRRect doesn't support scaling of empty rects.
    return;
  }
  if (!x_scale || !y_scale) {
    // SkRRect doesn't support scaling TO an empty rect.
    skrrect_ = SkRRect::MakeEmpty();
    return;
  }
  SkMatrix scale = SkMatrix::Scale(x_scale, y_scale);
  SkRRect result;
  bool success = skrrect_.transform(scale, &result);
  DCHECK(success);
  skrrect_ = result;
}

void RRectF::Offset(float horizontal, float vertical) {
  skrrect_.offset(horizontal, vertical);
}

const RRectF& RRectF::operator+=(const gfx::Vector2dF& offset) {
  Offset(offset.x(), offset.y());
  return *this;
}

const RRectF& RRectF::operator-=(const gfx::Vector2dF& offset) {
  Offset(-offset.x(), -offset.y());
  return *this;
}

std::string RRectF::ToString() const {
  std::stringstream ss;
  ss << std::fixed << std::setprecision(3);
  ss << rect().origin().x() << "," << rect().origin().y() << " "
     << rect().size().width() << "x" << rect().size().height();
  Type type = this->GetType();
  if (type <= Type::kRect) {
    ss << ", rectangular";
  } else if (type <= Type::kSingle) {
    ss << ", radius " << GetSimpleRadius();
  } else if (type <= Type::kSimple) {
    gfx::Vector2dF radii = GetSimpleRadii();
    ss << ", x_rad " << radii.x() << ", y_rad " << radii.y();
  } else {
    ss << ",";
    const Corner corners[] = {Corner::kUpperLeft, Corner::kUpperRight,
                              Corner::kLowerRight, Corner::kLowerLeft};
    for (const auto& c : corners) {
      auto this_corner = GetCornerRadii(c);
      ss << " [" << this_corner.x() << " " << this_corner.y() << "]";
    }
  }
  return ss.str();
}

namespace {
inline bool AboveTol(float val1, float val2, float tolerance) {
  return (std::abs(val1 - val2) > tolerance);
}
}  // namespace

bool RRectF::ApproximatelyEqual(const RRectF& rect, float tolerance) const {
  if (AboveTol(skrrect_.rect().x(), rect.skrrect_.rect().x(), tolerance) ||
      AboveTol(skrrect_.rect().y(), rect.skrrect_.rect().y(), tolerance) ||
      AboveTol(skrrect_.width(), rect.skrrect_.width(), tolerance) ||
      AboveTol(skrrect_.height(), rect.skrrect_.height(), tolerance))
    return false;
  for (int i = 0; i < 4; i++) {
    SkVector r1 = skrrect_.radii(SkRRect::Corner(i));
    SkVector r2 = rect.skrrect_.radii(SkRRect::Corner(i));
    if (std::abs(r1.x() - r2.x()) > tolerance ||
        std::abs(r1.y() - r2.y()) > tolerance) {
      return false;
    }
  }
  return true;
}

}  // namespace gfx
