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

#include "ui/compositor_extra/shadow.h"

#include "ui/base/resource/resource_bundle.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/shadow_util.h"

namespace ui {

namespace {

// Duration for opacity animation in milliseconds.
constexpr int kShadowAnimationDurationMs = 100;

}  // namespace

Shadow::Shadow() : shadow_layer_owner_(this) {}

Shadow::~Shadow() = default;

void Shadow::Init(int elevation) {
  DCHECK_GE(elevation, 0);
  desired_elevation_ = elevation;
  SetLayer(std::make_unique<ui::Layer>(ui::LAYER_NOT_DRAWN));
  layer()->SetName("Shadow Parent Container");
  RecreateShadowLayer();
}

void Shadow::SetContentBounds(const gfx::Rect& content_bounds) {
  // When the window moves but doesn't change size, this is a no-op. (The
  // origin stays the same in this case.)
  if (content_bounds == content_bounds_)
    return;

  content_bounds_ = content_bounds;
  UpdateLayerBounds();
}

void Shadow::SetElevation(int elevation) {
  DCHECK_GE(elevation, 0);
  if (desired_elevation_ == elevation)
    return;

  desired_elevation_ = elevation;

  // Stop waiting for any as yet unfinished implicit animations.
  StopObservingImplicitAnimations();

  // The old shadow layer is the new fading out layer.
  DCHECK(shadow_layer());
  fading_layer_owner_.Reset(shadow_layer_owner_.ReleaseLayer());
  RecreateShadowLayer();
  shadow_layer()->SetOpacity(0.f);

  {
    // Observe the fade out animation so we can clean up the layer when done.
    ui::ScopedLayerAnimationSettings settings(fading_layer()->GetAnimator());
    settings.AddObserver(this);
    settings.SetTransitionDuration(
        base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs));
    fading_layer()->SetOpacity(0.f);
  }

  {
    // We don't care to observe this one.
    ui::ScopedLayerAnimationSettings settings(shadow_layer()->GetAnimator());
    settings.SetTransitionDuration(
        base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs));
    shadow_layer()->SetOpacity(1.f);
  }
}

void Shadow::SetRoundedCornerRadius(int rounded_corner_radius) {
  DCHECK_GE(rounded_corner_radius, 0);
  if (rounded_corner_radius_ == rounded_corner_radius)
    return;

  rounded_corner_radius_ = rounded_corner_radius;
  UpdateLayerBounds();
}

void Shadow::OnImplicitAnimationsCompleted() {
  std::unique_ptr<ui::Layer> to_be_deleted = fading_layer_owner_.ReleaseLayer();
  // The size needed for layer() may be smaller now that |fading_layer()| is
  // removed.
  UpdateLayerBounds();
}

// -----------------------------------------------------------------------------
// Shadow::ShadowLayerOwner:

Shadow::ShadowLayerOwner::ShadowLayerOwner(Shadow* owner,
                                           std::unique_ptr<Layer> layer)
    : LayerOwner(std::move(layer)), owner_shadow_(owner) {}

Shadow::ShadowLayerOwner::~ShadowLayerOwner() = default;

std::unique_ptr<Layer> Shadow::ShadowLayerOwner::RecreateLayer() {
  auto result = ui::LayerOwner::RecreateLayer();
  // Now update the newly recreated shadow layer with the correct nine patch
  // image details.
  owner_shadow_->details_ = nullptr;
  owner_shadow_->UpdateLayerBounds();
  return result;
}

// -----------------------------------------------------------------------------
// Shadow:

void Shadow::RecreateShadowLayer() {
  shadow_layer_owner_.Reset(std::make_unique<ui::Layer>(ui::LAYER_NINE_PATCH));
  shadow_layer()->SetName("Shadow");
  shadow_layer()->SetVisible(true);
  shadow_layer()->SetFillsBoundsOpaquely(false);
  layer()->Add(shadow_layer());

  UpdateLayerBounds();
}

void Shadow::UpdateLayerBounds() {
  if (content_bounds_.IsEmpty())
    return;

  // The ninebox assumption breaks down when the window is too small for the
  // desired elevation. The height/width of |blur_region| will be 4 * elevation
  // (see ShadowDetails::Get), so cap elevation at the most we can handle.
  const int smaller_dimension =
      std::min(content_bounds_.width(), content_bounds_.height());
  const int size_adjusted_elevation =
      std::min((smaller_dimension - 2 * rounded_corner_radius_) / 4,
               static_cast<int>(desired_elevation_));
  const auto& details =
      gfx::ShadowDetails::Get(size_adjusted_elevation, rounded_corner_radius_);
  gfx::Insets blur_region = gfx::ShadowValue::GetBlurRegion(details.values) +
                            gfx::Insets(rounded_corner_radius_);
  // Update |shadow_layer()| if details changed and it has been updated in
  // the past (|details_| is set), or elevation is non-zero.
  if ((&details != details_) && (details_ || size_adjusted_elevation)) {
    shadow_layer()->UpdateNinePatchLayerImage(details.ninebox_image);
    // The ninebox grid is defined in terms of the image size. The shadow blurs
    // in both inward and outward directions from the edge of the contents, so
    // the aperture goes further inside the image than the shadow margins (which
    // represent exterior blur).
    gfx::Rect aperture(details.ninebox_image.size());
    aperture.Inset(blur_region);
    shadow_layer()->UpdateNinePatchLayerAperture(aperture);
    details_ = &details;
  }

  // Shadow margins are negative, so this expands outwards from
  // |content_bounds_|.
  const gfx::Insets margins = gfx::ShadowValue::GetMargin(details.values);
  gfx::Rect new_layer_bounds = content_bounds_;
  new_layer_bounds.Inset(margins);
  gfx::Rect shadow_layer_bounds(new_layer_bounds.size());

  // When there's an old shadow fading out, the bounds of layer() have to be
  // big enough to encompass both shadows.
  if (fading_layer()) {
    const gfx::Rect old_layer_bounds = layer()->bounds();
    gfx::Rect combined_layer_bounds = old_layer_bounds;
    combined_layer_bounds.Union(new_layer_bounds);
    layer()->SetBounds(combined_layer_bounds);

    // If this is reached via SetContentBounds, we might hypothetically need
    // to change the size of the fading layer, but the fade is so fast it's
    // not really an issue.
    gfx::Rect fading_layer_bounds(fading_layer()->bounds());
    fading_layer_bounds.Offset(old_layer_bounds.origin() -
                               combined_layer_bounds.origin());
    fading_layer()->SetBounds(fading_layer_bounds);

    shadow_layer_bounds.Offset(new_layer_bounds.origin() -
                               combined_layer_bounds.origin());
  } else {
    layer()->SetBounds(new_layer_bounds);
  }

  shadow_layer()->SetBounds(shadow_layer_bounds);

  // Occlude the region inside the bounding box. Occlusion uses shadow layer
  // space. See nine_patch_layer.h for more context on what's going on here.
  gfx::Rect occlusion_bounds(shadow_layer_bounds.size());
  occlusion_bounds.Inset(-margins + gfx::Insets(rounded_corner_radius_));
  shadow_layer()->UpdateNinePatchOcclusion(occlusion_bounds);

  // The border is the same inset as the aperture.
  shadow_layer()->UpdateNinePatchLayerBorder(
      gfx::Rect(blur_region.left(), blur_region.top(), blur_region.width(),
                blur_region.height()));
}

}  // namespace ui
