// 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/wm/core/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"
#include "ui/wm/core/shadow_types.h"

namespace wm {

namespace {

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

// Default rounded corner radius. Shadow::SetRoundedCornerRadius can
// be used to override this for elements with a different rounded
// corner radius.
const int kDefaultRoundedCornerRadius = 2;

}  // namespace

Shadow::Shadow()
    : desired_elevation_(ShadowElevation::NONE),
      rounded_corner_radius_(kDefaultRoundedCornerRadius) {}

Shadow::~Shadow() {}

void Shadow::Init(ShadowElevation elevation) {
  DCHECK_NE(ShadowElevation::DEFAULT, elevation);
  desired_elevation_ = elevation;
  layer_.reset(new ui::Layer(ui::LAYER_NOT_DRAWN));
  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(ShadowElevation elevation) {
  DCHECK_NE(ShadowElevation::DEFAULT, elevation);
  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_ = std::move(shadow_layer_);
  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() {
  fading_layer_.reset();
  // The size needed for layer() may be smaller now that |fading_layer_| is
  // removed.
  UpdateLayerBounds();
}

void Shadow::RecreateShadowLayer() {
  shadow_layer_.reset(new ui::Layer(ui::LAYER_NINE_PATCH));
  shadow_layer_->set_name("Shadow");
  shadow_layer_->SetVisible(true);
  shadow_layer_->SetFillsBoundsOpaquely(false);
  layer()->Add(shadow_layer_.get());

  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_);
  if (size_adjusted_elevation != effective_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);
  }
  effective_elevation_ = size_adjusted_elevation;

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