// 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/scoped_layer_animation_settings.h"

#include <stddef.h>

#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/layer_observer.h"

namespace {

const int kDefaultTransitionDurationMs = 200;

template <typename Trait>
class ScopedLayerAnimationObserver : public ui::ImplicitAnimationObserver,
                                     public ui::LayerObserver {
 public:
  ScopedLayerAnimationObserver(ui::Layer* layer) : layer_(layer) {
    layer_->AddObserver(this);
    Trait::AddRequest(layer_);
  }
  ~ScopedLayerAnimationObserver() override {
    if (layer_)
      layer_->RemoveObserver(this);
  }

  // ui::ImplicitAnimationObserver overrides:
  void OnImplicitAnimationsCompleted() override {
    // If animation finishes before |layer_| is destoyed, we will remove the
    // request applied on the layer and remove |this| from the |layer_|
    // observer list when deleting |this|.
    if (layer_) {
      Trait::RemoveRequest(layer_);
      layer_->GetAnimator()->RemoveAndDestroyOwnedObserver(this);
    }
  }

  // ui::LayerObserver overrides:
  void LayerDestroyed(ui::Layer* layer) override {
    // If the animation is still going past layer destruction then we want the
    // layer to keep the request until the animation has finished. We will defer
    // deleting |this| until the animation finishes.
    layer_->RemoveObserver(this);
    layer_ = nullptr;
  }

 private:
  ui::Layer* layer_;

  DISALLOW_COPY_AND_ASSIGN(ScopedLayerAnimationObserver);
};

struct RenderSurfaceCachingTrait {
  static void AddRequest(ui::Layer* layer) {
    layer->AddCacheRenderSurfaceRequest();
  }
  static void RemoveRequest(ui::Layer* layer) {
    layer->RemoveCacheRenderSurfaceRequest();
  }
};
using ScopedRenderSurfaceCaching =
    ScopedLayerAnimationObserver<RenderSurfaceCachingTrait>;

struct DeferredPaintingTrait {
  static void AddRequest(ui::Layer* layer) { layer->AddDeferredPaintRequest(); }
  static void RemoveRequest(ui::Layer* layer) {
    layer->RemoveDeferredPaintRequest();
  }
};
using ScopedDeferredPainting =
    ScopedLayerAnimationObserver<DeferredPaintingTrait>;

struct TrilinearFilteringTrait {
  static void AddRequest(ui::Layer* layer) {
    layer->AddTrilinearFilteringRequest();
  }
  static void RemoveRequest(ui::Layer* layer) {
    layer->RemoveTrilinearFilteringRequest();
  }
};
using ScopedTrilinearFiltering =
    ScopedLayerAnimationObserver<TrilinearFilteringTrait>;

void AddObserverToSettings(
    ui::ScopedLayerAnimationSettings* settings,
    std::unique_ptr<ui::ImplicitAnimationObserver> observer) {
  settings->AddObserver(observer.get());
  settings->GetAnimator()->AddOwnedObserver(std::move(observer));
}

void AddScopedDeferredPaintingObserverRecursive(
    ui::Layer* layer,
    ui::ScopedLayerAnimationSettings* settings) {
  auto observer = std::make_unique<ScopedDeferredPainting>(layer);
  AddObserverToSettings(settings, std::move(observer));
  for (auto* child : layer->children())
    AddScopedDeferredPaintingObserverRecursive(child, settings);
}

}  // namespace

namespace ui {

// ScopedLayerAnimationSettings ------------------------------------------------
ScopedLayerAnimationSettings::ScopedLayerAnimationSettings(
    scoped_refptr<LayerAnimator> animator)
    : animator_(animator),
      old_is_transition_duration_locked_(
          animator->is_transition_duration_locked_),
      old_transition_duration_(animator->GetTransitionDuration()),
      old_tween_type_(animator->tween_type()),
      old_preemption_strategy_(animator->preemption_strategy()) {
  SetTransitionDuration(
      base::TimeDelta::FromMilliseconds(kDefaultTransitionDurationMs));
}

ScopedLayerAnimationSettings::~ScopedLayerAnimationSettings() {
  animator_->set_animation_metrics_reporter(nullptr);
  animator_->is_transition_duration_locked_ =
      old_is_transition_duration_locked_;
  animator_->SetTransitionDuration(old_transition_duration_);
  animator_->set_tween_type(old_tween_type_);
  animator_->set_preemption_strategy(old_preemption_strategy_);

  for (auto* observer : observers_) {
    // Directly remove |observer| from |LayerAnimator::observers_| rather than
    // calling LayerAnimator::RemoveObserver(), to avoid removing it from the
    // observer list of LayerAnimationSequences that have already been
    // scheduled.
    animator_->observers_.RemoveObserver(observer);
    observer->SetActive(true);
  }
}

void ScopedLayerAnimationSettings::AddObserver(
    ImplicitAnimationObserver* observer) {
  observers_.insert(observer);
  animator_->AddObserver(observer);
}

void ScopedLayerAnimationSettings::SetAnimationMetricsReporter(
    AnimationMetricsReporter* reporter) {
  animator_->set_animation_metrics_reporter(reporter);
}

void ScopedLayerAnimationSettings::SetTransitionDuration(
    base::TimeDelta duration) {
  animator_->SetTransitionDuration(duration);
}

base::TimeDelta ScopedLayerAnimationSettings::GetTransitionDuration() const {
  return animator_->GetTransitionDuration();
}

void ScopedLayerAnimationSettings::LockTransitionDuration() {
  animator_->is_transition_duration_locked_ = true;
}

void ScopedLayerAnimationSettings::SetTweenType(gfx::Tween::Type tween_type) {
  animator_->set_tween_type(tween_type);
}

gfx::Tween::Type ScopedLayerAnimationSettings::GetTweenType() const {
  return animator_->tween_type();
}

void ScopedLayerAnimationSettings::SetPreemptionStrategy(
    LayerAnimator::PreemptionStrategy strategy) {
  animator_->set_preemption_strategy(strategy);
}

LayerAnimator::PreemptionStrategy
ScopedLayerAnimationSettings::GetPreemptionStrategy() const {
  return animator_->preemption_strategy();
}

void ScopedLayerAnimationSettings::CacheRenderSurface() {
  auto observer = std::make_unique<ScopedRenderSurfaceCaching>(
      animator_->delegate()->GetLayer());
  AddObserverToSettings(this, std::move(observer));
}

void ScopedLayerAnimationSettings::DeferPaint() {
  AddScopedDeferredPaintingObserverRecursive(animator_->delegate()->GetLayer(),
                                             this);
}

void ScopedLayerAnimationSettings::TrilinearFiltering() {
  auto observer = std::make_unique<ScopedTrilinearFiltering>(
      animator_->delegate()->GetLayer());
  AddObserverToSettings(this, std::move(observer));
}

}  // namespace ui
