// Copyright 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 "cc/animation/layer_animation_controller.h"

#include <algorithm>
#include <vector>

#include "cc/animation/animation.h"
#include "cc/animation/animation_delegate.h"
#include "cc/animation/animation_registrar.h"
#include "cc/animation/keyframed_animation_curve.h"
#include "cc/animation/layer_animation_value_observer.h"
#include "cc/animation/layer_animation_value_provider.h"
#include "cc/animation/scroll_offset_animation_curve.h"
#include "cc/base/scoped_ptr_algorithm.h"
#include "cc/output/filter_operations.h"
#include "ui/gfx/geometry/box_f.h"
#include "ui/gfx/transform.h"

namespace cc {

LayerAnimationController::LayerAnimationController(int id)
    : registrar_(0),
      id_(id),
      is_active_(false),
      value_provider_(nullptr),
      layer_animation_delegate_(nullptr),
      needs_to_start_animations_(false) {
}

LayerAnimationController::~LayerAnimationController() {
  if (registrar_)
    registrar_->UnregisterAnimationController(this);
}

scoped_refptr<LayerAnimationController> LayerAnimationController::Create(
    int id) {
  return make_scoped_refptr(new LayerAnimationController(id));
}

void LayerAnimationController::PauseAnimation(int animation_id,
                                              base::TimeDelta time_offset) {
  for (size_t i = 0; i < animations_.size(); ++i) {
    if (animations_[i]->id() == animation_id) {
      animations_[i]->SetRunState(Animation::Paused,
                                  time_offset + animations_[i]->start_time());
    }
  }
}

struct HasAnimationId {
  explicit HasAnimationId(int id) : id_(id) {}
  bool operator()(Animation* animation) const {
    return animation->id() == id_;
  }

 private:
  int id_;
};

void LayerAnimationController::RemoveAnimation(int animation_id) {
  animations_.erase(cc::remove_if(&animations_,
                                  animations_.begin(),
                                  animations_.end(),
                                  HasAnimationId(animation_id)),
                    animations_.end());
  UpdateActivation(NormalActivation);
}

struct HasAnimationIdAndProperty {
  HasAnimationIdAndProperty(int id, Animation::TargetProperty target_property)
      : id_(id), target_property_(target_property) {}
  bool operator()(Animation* animation) const {
    return animation->id() == id_ &&
        animation->target_property() == target_property_;
  }

 private:
  int id_;
  Animation::TargetProperty target_property_;
};

void LayerAnimationController::RemoveAnimation(
    int animation_id,
    Animation::TargetProperty target_property) {
  animations_.erase(
      cc::remove_if(&animations_,
                    animations_.begin(),
                    animations_.end(),
                    HasAnimationIdAndProperty(animation_id, target_property)),
      animations_.end());
  UpdateActivation(NormalActivation);
}

void LayerAnimationController::AbortAnimations(
    Animation::TargetProperty target_property) {
  for (size_t i = 0; i < animations_.size(); ++i) {
    if (animations_[i]->target_property() == target_property &&
        !animations_[i]->is_finished())
      animations_[i]->SetRunState(Animation::Aborted, last_tick_time_);
  }
}

// Ensures that the list of active animations on the main thread and the impl
// thread are kept in sync.
void LayerAnimationController::PushAnimationUpdatesTo(
    LayerAnimationController* controller_impl) {
  DCHECK(this != controller_impl);
  if (!has_any_animation() && !controller_impl->has_any_animation())
    return;
  PurgeAnimationsMarkedForDeletion();
  PushNewAnimationsToImplThread(controller_impl);

  // Remove finished impl side animations only after pushing,
  // and only after the animations are deleted on the main thread
  // this insures we will never push an animation twice.
  RemoveAnimationsCompletedOnMainThread(controller_impl);

  PushPropertiesToImplThread(controller_impl);
  controller_impl->UpdateActivation(NormalActivation);
  UpdateActivation(NormalActivation);
}

void LayerAnimationController::Animate(base::TimeTicks monotonic_time) {
  DCHECK(!monotonic_time.is_null());
  if (!HasValueObserver())
    return;

  if (needs_to_start_animations_)
    StartAnimations(monotonic_time);
  TickAnimations(monotonic_time);
  last_tick_time_ = monotonic_time;
}

void LayerAnimationController::AccumulatePropertyUpdates(
    base::TimeTicks monotonic_time,
    AnimationEventsVector* events) {
  if (!events)
    return;

  for (size_t i = 0; i < animations_.size(); ++i) {
    Animation* animation = animations_[i];
    if (!animation->is_impl_only())
      continue;

    if (!animation->InEffect(monotonic_time))
      continue;

    base::TimeDelta trimmed =
        animation->TrimTimeToCurrentIteration(monotonic_time);
    switch (animation->target_property()) {
      case Animation::Opacity: {
        AnimationEvent event(AnimationEvent::PropertyUpdate,
                             id_,
                             animation->group(),
                             Animation::Opacity,
                             monotonic_time);
        const FloatAnimationCurve* float_animation_curve =
            animation->curve()->ToFloatAnimationCurve();
        event.opacity = float_animation_curve->GetValue(trimmed);
        event.is_impl_only = true;
        events->push_back(event);
        break;
      }

      case Animation::Transform: {
        AnimationEvent event(AnimationEvent::PropertyUpdate,
                             id_,
                             animation->group(),
                             Animation::Transform,
                             monotonic_time);
        const TransformAnimationCurve* transform_animation_curve =
            animation->curve()->ToTransformAnimationCurve();
        event.transform = transform_animation_curve->GetValue(trimmed);
        event.is_impl_only = true;
        events->push_back(event);
        break;
      }

      case Animation::Filter: {
        AnimationEvent event(AnimationEvent::PropertyUpdate,
                             id_,
                             animation->group(),
                             Animation::Filter,
                             monotonic_time);
        const FilterAnimationCurve* filter_animation_curve =
            animation->curve()->ToFilterAnimationCurve();
        event.filters = filter_animation_curve->GetValue(trimmed);
        event.is_impl_only = true;
        events->push_back(event);
        break;
      }

      case Animation::BackgroundColor: { break; }

      case Animation::ScrollOffset: {
        // Impl-side changes to scroll offset are already sent back to the
        // main thread (e.g. for user-driven scrolling), so a PropertyUpdate
        // isn't needed.
        break;
      }

      case Animation::TargetPropertyEnumSize:
        NOTREACHED();
    }
  }
}

void LayerAnimationController::UpdateState(bool start_ready_animations,
                                           AnimationEventsVector* events) {
  if (!HasActiveValueObserver())
    return;

  // Animate hasn't been called, this happens if an observer has been added
  // between the Commit and Draw phases.
  if (last_tick_time_ == base::TimeTicks())
    return;

  if (start_ready_animations)
    PromoteStartedAnimations(last_tick_time_, events);

  MarkFinishedAnimations(last_tick_time_);
  MarkAnimationsForDeletion(last_tick_time_, events);

  if (needs_to_start_animations_ && start_ready_animations) {
    StartAnimations(last_tick_time_);
    PromoteStartedAnimations(last_tick_time_, events);
  }

  AccumulatePropertyUpdates(last_tick_time_, events);

  UpdateActivation(NormalActivation);
}

struct AffectsNoObservers {
  bool operator()(Animation* animation) const {
    return !animation->affects_active_observers() &&
           !animation->affects_pending_observers();
  }
};

void LayerAnimationController::ActivateAnimations() {
  for (size_t i = 0; i < animations_.size(); ++i) {
    animations_[i]->set_affects_active_observers(
        animations_[i]->affects_pending_observers());
  }
  animations_.erase(cc::remove_if(&animations_,
                                  animations_.begin(),
                                  animations_.end(),
                                  AffectsNoObservers()),
                    animations_.end());
  UpdateActivation(NormalActivation);
}

void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) {
  animations_.push_back(animation.Pass());
  needs_to_start_animations_ = true;
  UpdateActivation(NormalActivation);
}

Animation* LayerAnimationController::GetAnimation(
    int group_id,
    Animation::TargetProperty target_property) const {
  for (size_t i = 0; i < animations_.size(); ++i)
    if (animations_[i]->group() == group_id &&
        animations_[i]->target_property() == target_property)
      return animations_[i];
  return 0;
}

Animation* LayerAnimationController::GetAnimation(
    Animation::TargetProperty target_property) const {
  for (size_t i = 0; i < animations_.size(); ++i) {
    size_t index = animations_.size() - i - 1;
    if (animations_[index]->target_property() == target_property)
      return animations_[index];
  }
  return 0;
}

bool LayerAnimationController::HasActiveAnimation() const {
  for (size_t i = 0; i < animations_.size(); ++i) {
    if (!animations_[i]->is_finished())
      return true;
  }
  return false;
}

bool LayerAnimationController::IsAnimatingProperty(
    Animation::TargetProperty target_property) const {
  for (size_t i = 0; i < animations_.size(); ++i) {
    if (!animations_[i]->is_finished() &&
        animations_[i]->InEffect(last_tick_time_) &&
        animations_[i]->target_property() == target_property)
      return true;
  }
  return false;
}

void LayerAnimationController::SetAnimationRegistrar(
    AnimationRegistrar* registrar) {
  if (registrar_ == registrar)
    return;

  if (registrar_)
    registrar_->UnregisterAnimationController(this);

  registrar_ = registrar;
  if (registrar_)
    registrar_->RegisterAnimationController(this);

  UpdateActivation(ForceActivation);
}

void LayerAnimationController::NotifyAnimationStarted(
    const AnimationEvent& event) {
  if (event.is_impl_only) {
    FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
                      OnAnimationStarted(event));
    if (layer_animation_delegate_)
      layer_animation_delegate_->NotifyAnimationStarted(
          event.monotonic_time, event.target_property, event.group_id);
    return;
  }

  for (size_t i = 0; i < animations_.size(); ++i) {
    if (animations_[i]->group() == event.group_id &&
        animations_[i]->target_property() == event.target_property &&
        animations_[i]->needs_synchronized_start_time()) {
      animations_[i]->set_needs_synchronized_start_time(false);
      if (!animations_[i]->has_set_start_time())
        animations_[i]->set_start_time(event.monotonic_time);

      FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
                        OnAnimationStarted(event));
      if (layer_animation_delegate_)
        layer_animation_delegate_->NotifyAnimationStarted(
            event.monotonic_time, event.target_property, event.group_id);

      return;
    }
  }
}

void LayerAnimationController::NotifyAnimationFinished(
    const AnimationEvent& event) {
  if (event.is_impl_only) {
    if (layer_animation_delegate_)
      layer_animation_delegate_->NotifyAnimationFinished(
          event.monotonic_time, event.target_property, event.group_id);
    return;
  }

  for (size_t i = 0; i < animations_.size(); ++i) {
    if (animations_[i]->group() == event.group_id &&
        animations_[i]->target_property() == event.target_property) {
      animations_[i]->set_received_finished_event(true);
      if (layer_animation_delegate_)
        layer_animation_delegate_->NotifyAnimationFinished(
            event.monotonic_time, event.target_property, event.group_id);

      return;
    }
  }
}

void LayerAnimationController::NotifyAnimationAborted(
    const AnimationEvent& event) {
  for (size_t i = 0; i < animations_.size(); ++i) {
    if (animations_[i]->group() == event.group_id &&
        animations_[i]->target_property() == event.target_property) {
      animations_[i]->SetRunState(Animation::Aborted, event.monotonic_time);
    }
  }
}

void LayerAnimationController::NotifyAnimationPropertyUpdate(
    const AnimationEvent& event) {
  bool notify_active_observers = true;
  bool notify_pending_observers = true;
  switch (event.target_property) {
    case Animation::Opacity:
      NotifyObserversOpacityAnimated(
          event.opacity, notify_active_observers, notify_pending_observers);
      break;
    case Animation::Transform:
      NotifyObserversTransformAnimated(
          event.transform, notify_active_observers, notify_pending_observers);
      break;
    default:
      NOTREACHED();
  }
}

void LayerAnimationController::AddValueObserver(
    LayerAnimationValueObserver* observer) {
  if (!value_observers_.HasObserver(observer))
    value_observers_.AddObserver(observer);
}

void LayerAnimationController::RemoveValueObserver(
    LayerAnimationValueObserver* observer) {
  value_observers_.RemoveObserver(observer);
}

void LayerAnimationController::AddEventObserver(
    LayerAnimationEventObserver* observer) {
  if (!event_observers_.HasObserver(observer))
    event_observers_.AddObserver(observer);
}

void LayerAnimationController::RemoveEventObserver(
    LayerAnimationEventObserver* observer) {
  event_observers_.RemoveObserver(observer);
}

bool LayerAnimationController::HasFilterAnimationThatInflatesBounds() const {
  for (size_t i = 0; i < animations_.size(); ++i) {
    if (!animations_[i]->is_finished() &&
        animations_[i]->target_property() == Animation::Filter &&
        animations_[i]
            ->curve()
            ->ToFilterAnimationCurve()
            ->HasFilterThatMovesPixels())
      return true;
  }

  return false;
}

bool LayerAnimationController::HasTransformAnimationThatInflatesBounds() const {
  return IsAnimatingProperty(Animation::Transform);
}

bool LayerAnimationController::FilterAnimationBoundsForBox(
    const gfx::BoxF& box, gfx::BoxF* bounds) const {
  // TODO(avallee): Implement.
  return false;
}

bool LayerAnimationController::TransformAnimationBoundsForBox(
    const gfx::BoxF& box,
    gfx::BoxF* bounds) const {
  DCHECK(HasTransformAnimationThatInflatesBounds())
      << "TransformAnimationBoundsForBox will give incorrect results if there "
      << "are no transform animations affecting bounds, non-animated transform "
      << "is not known";

  // Compute bounds based on animations for which is_finished() is false.
  // Do nothing if there are no such animations; in this case, it is assumed
  // that callers will take care of computing bounds based on the owning layer's
  // actual transform.
  *bounds = gfx::BoxF();
  for (size_t i = 0; i < animations_.size(); ++i) {
    if (animations_[i]->is_finished() ||
        animations_[i]->target_property() != Animation::Transform)
      continue;

    const TransformAnimationCurve* transform_animation_curve =
        animations_[i]->curve()->ToTransformAnimationCurve();
    gfx::BoxF animation_bounds;
    bool success =
        transform_animation_curve->AnimatedBoundsForBox(box, &animation_bounds);
    if (!success)
      return false;
    bounds->Union(animation_bounds);
  }

  return true;
}

bool LayerAnimationController::HasAnimationThatAffectsScale() const {
  for (size_t i = 0; i < animations_.size(); ++i) {
    if (animations_[i]->is_finished() ||
        animations_[i]->target_property() != Animation::Transform)
      continue;

    const TransformAnimationCurve* transform_animation_curve =
        animations_[i]->curve()->ToTransformAnimationCurve();
    if (transform_animation_curve->AffectsScale())
      return true;
  }

  return false;
}

bool LayerAnimationController::HasOnlyTranslationTransforms() const {
  for (size_t i = 0; i < animations_.size(); ++i) {
    if (animations_[i]->is_finished() ||
        animations_[i]->target_property() != Animation::Transform)
      continue;

    const TransformAnimationCurve* transform_animation_curve =
        animations_[i]->curve()->ToTransformAnimationCurve();
    if (!transform_animation_curve->IsTranslation())
      return false;
  }

  return true;
}

bool LayerAnimationController::AnimationsPreserveAxisAlignment() const {
  for (size_t i = 0; i < animations_.size(); ++i) {
    if (animations_[i]->is_finished() ||
        animations_[i]->target_property() != Animation::Transform)
      continue;

    const TransformAnimationCurve* transform_animation_curve =
        animations_[i]->curve()->ToTransformAnimationCurve();
    if (!transform_animation_curve->PreservesAxisAlignment())
      return false;
  }

  return true;
}

bool LayerAnimationController::MaximumTargetScale(float* max_scale) const {
  *max_scale = 0.f;
  for (size_t i = 0; i < animations_.size(); ++i) {
    if (animations_[i]->is_finished() ||
        animations_[i]->target_property() != Animation::Transform)
      continue;

    bool forward_direction = true;
    switch (animations_[i]->direction()) {
      case Animation::Normal:
      case Animation::Alternate:
        forward_direction = animations_[i]->playback_rate() >= 0.0;
        break;
      case Animation::Reverse:
      case Animation::AlternateReverse:
        forward_direction = animations_[i]->playback_rate() < 0.0;
        break;
    }

    const TransformAnimationCurve* transform_animation_curve =
        animations_[i]->curve()->ToTransformAnimationCurve();
    float animation_scale = 0.f;
    if (!transform_animation_curve->MaximumTargetScale(forward_direction,
                                                       &animation_scale))
      return false;
    *max_scale = std::max(*max_scale, animation_scale);
  }

  return true;
}

void LayerAnimationController::PushNewAnimationsToImplThread(
    LayerAnimationController* controller_impl) const {
  // Any new animations owned by the main thread's controller are cloned and
  // add to the impl thread's controller.
  for (size_t i = 0; i < animations_.size(); ++i) {
    // If the animation is already running on the impl thread, there is no
    // need to copy it over.
    if (controller_impl->GetAnimation(animations_[i]->group(),
                                      animations_[i]->target_property()))
      continue;

    // If the animation is not running on the impl thread, it does not
    // necessarily mean that it needs to be copied over and started; it may
    // have already finished. In this case, the impl thread animation will
    // have already notified that it has started and the main thread animation
    // will no longer need
    // a synchronized start time.
    if (!animations_[i]->needs_synchronized_start_time())
      continue;

    // Scroll animations always start at the current scroll offset.
    if (animations_[i]->target_property() == Animation::ScrollOffset) {
      gfx::ScrollOffset current_scroll_offset;
      if (controller_impl->value_provider_) {
        current_scroll_offset =
            controller_impl->value_provider_->ScrollOffsetForAnimation();
      } else {
        // The owning layer isn't yet in the active tree, so the main thread
        // scroll offset will be up-to-date.
        current_scroll_offset = value_provider_->ScrollOffsetForAnimation();
      }
      animations_[i]->curve()->ToScrollOffsetAnimationCurve()->SetInitialValue(
          current_scroll_offset);
    }

    // The new animation should be set to run as soon as possible.
    Animation::RunState initial_run_state =
        Animation::WaitingForTargetAvailability;
    scoped_ptr<Animation> to_add(
        animations_[i]->CloneAndInitialize(initial_run_state));
    DCHECK(!to_add->needs_synchronized_start_time());
    to_add->set_affects_active_observers(false);
    controller_impl->AddAnimation(to_add.Pass());
  }
}

static bool IsCompleted(
    Animation* animation,
    const LayerAnimationController* main_thread_controller) {
  if (animation->is_impl_only()) {
    return (animation->run_state() == Animation::WaitingForDeletion);
  } else {
    return !main_thread_controller->GetAnimation(animation->group(),
                                                 animation->target_property());
  }
}

static bool AffectsActiveOnlyAndIsWaitingForDeletion(Animation* animation) {
  return animation->run_state() == Animation::WaitingForDeletion &&
         !animation->affects_pending_observers();
}

void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
    LayerAnimationController* controller_impl) const {
  // Animations removed on the main thread should no longer affect pending
  // observers, and should stop affecting active observers after the next call
  // to ActivateAnimations. If already WaitingForDeletion, they can be removed
  // immediately.
  ScopedPtrVector<Animation>& animations = controller_impl->animations_;
  for (size_t i = 0; i < animations.size(); ++i) {
    if (IsCompleted(animations[i], this))
      animations[i]->set_affects_pending_observers(false);
  }
  animations.erase(cc::remove_if(&animations,
                                 animations.begin(),
                                 animations.end(),
                                 AffectsActiveOnlyAndIsWaitingForDeletion),
                   animations.end());
}

void LayerAnimationController::PushPropertiesToImplThread(
    LayerAnimationController* controller_impl) const {
  for (size_t i = 0; i < animations_.size(); ++i) {
    Animation* current_impl = controller_impl->GetAnimation(
        animations_[i]->group(), animations_[i]->target_property());
    if (current_impl)
      animations_[i]->PushPropertiesTo(current_impl);
  }
}

void LayerAnimationController::StartAnimations(base::TimeTicks monotonic_time) {
  DCHECK(needs_to_start_animations_);
  needs_to_start_animations_ = false;
  // First collect running properties affecting each type of observer.
  TargetProperties blocked_properties_for_active_observers;
  TargetProperties blocked_properties_for_pending_observers;
  std::vector<size_t> animations_waiting_for_target;

  animations_waiting_for_target.reserve(animations_.size());
  for (size_t i = 0; i < animations_.size(); ++i) {
    if (animations_[i]->run_state() == Animation::Starting ||
        animations_[i]->run_state() == Animation::Running) {
      if (animations_[i]->affects_active_observers()) {
        blocked_properties_for_active_observers.insert(
            animations_[i]->target_property());
      }
      if (animations_[i]->affects_pending_observers()) {
        blocked_properties_for_pending_observers.insert(
            animations_[i]->target_property());
      }
    } else if (animations_[i]->run_state() ==
               Animation::WaitingForTargetAvailability) {
      animations_waiting_for_target.push_back(i);
    }
  }

  for (size_t i = 0; i < animations_waiting_for_target.size(); ++i) {
      // Collect all properties for animations with the same group id (they
      // should all also be in the list of animations).
    size_t animation_index = animations_waiting_for_target[i];
    Animation* animation_waiting_for_target = animations_[animation_index];
    // Check for the run state again even though the animation was waiting
    // for target because it might have changed the run state while handling
    // previous animation in this loop (if they belong to same group).
    if (animation_waiting_for_target->run_state() ==
        Animation::WaitingForTargetAvailability) {
      TargetProperties enqueued_properties;
      bool affects_active_observers =
          animation_waiting_for_target->affects_active_observers();
      bool affects_pending_observers =
          animation_waiting_for_target->affects_pending_observers();
      enqueued_properties.insert(
          animation_waiting_for_target->target_property());
      for (size_t j = animation_index + 1; j < animations_.size(); ++j) {
        if (animation_waiting_for_target->group() == animations_[j]->group()) {
          enqueued_properties.insert(animations_[j]->target_property());
          affects_active_observers |=
              animations_[j]->affects_active_observers();
          affects_pending_observers |=
              animations_[j]->affects_pending_observers();
        }
      }

      // Check to see if intersection of the list of properties affected by
      // the group and the list of currently blocked properties is null, taking
      // into account the type(s) of observers affected by the group. In any
      // case, the group's target properties need to be added to the lists of
      // blocked properties.
      bool null_intersection = true;
      for (TargetProperties::iterator p_iter = enqueued_properties.begin();
           p_iter != enqueued_properties.end();
           ++p_iter) {
        if (affects_active_observers &&
            !blocked_properties_for_active_observers.insert(*p_iter).second)
          null_intersection = false;
        if (affects_pending_observers &&
            !blocked_properties_for_pending_observers.insert(*p_iter).second)
          null_intersection = false;
      }

      // If the intersection is null, then we are free to start the animations
      // in the group.
      if (null_intersection) {
        animation_waiting_for_target->SetRunState(Animation::Starting,
                                                  monotonic_time);
        for (size_t j = animation_index + 1; j < animations_.size(); ++j) {
          if (animation_waiting_for_target->group() ==
              animations_[j]->group()) {
            animations_[j]->SetRunState(Animation::Starting, monotonic_time);
          }
        }
      } else {
        needs_to_start_animations_ = true;
      }
    }
  }
}

void LayerAnimationController::PromoteStartedAnimations(
    base::TimeTicks monotonic_time,
    AnimationEventsVector* events) {
  for (size_t i = 0; i < animations_.size(); ++i) {
    if (animations_[i]->run_state() == Animation::Starting &&
        animations_[i]->affects_active_observers()) {
      animations_[i]->SetRunState(Animation::Running, monotonic_time);
      if (!animations_[i]->has_set_start_time() &&
          !animations_[i]->needs_synchronized_start_time())
        animations_[i]->set_start_time(monotonic_time);
      if (events) {
        AnimationEvent started_event(AnimationEvent::Started,
                                     id_,
                                     animations_[i]->group(),
                                     animations_[i]->target_property(),
                                     monotonic_time);
        started_event.is_impl_only = animations_[i]->is_impl_only();
        if (started_event.is_impl_only)
          NotifyAnimationStarted(started_event);
        else
          events->push_back(started_event);
      }
    }
  }
}

void LayerAnimationController::MarkFinishedAnimations(
    base::TimeTicks monotonic_time) {
  for (size_t i = 0; i < animations_.size(); ++i) {
    if (animations_[i]->IsFinishedAt(monotonic_time) &&
        animations_[i]->run_state() != Animation::Aborted &&
        animations_[i]->run_state() != Animation::WaitingForDeletion)
      animations_[i]->SetRunState(Animation::Finished, monotonic_time);
  }
}

void LayerAnimationController::MarkAnimationsForDeletion(
    base::TimeTicks monotonic_time,
    AnimationEventsVector* events) {
  bool marked_animations_for_deletions = false;
  std::vector<size_t> animations_with_same_group_id;

  animations_with_same_group_id.reserve(animations_.size());
  // Non-aborted animations are marked for deletion after a corresponding
  // AnimationEvent::Finished event is sent or received. This means that if
  // we don't have an events vector, we must ensure that non-aborted animations
  // have received a finished event before marking them for deletion.
  for (size_t i = 0; i < animations_.size(); i++) {
    int group_id = animations_[i]->group();
    if (animations_[i]->run_state() == Animation::Aborted) {
      if (events && !animations_[i]->is_impl_only()) {
        AnimationEvent aborted_event(AnimationEvent::Aborted,
                                     id_,
                                     group_id,
                                     animations_[i]->target_property(),
                                     monotonic_time);
        events->push_back(aborted_event);
      }
      animations_[i]->SetRunState(Animation::WaitingForDeletion,
                                  monotonic_time);
      marked_animations_for_deletions = true;
      continue;
    }

    bool all_anims_with_same_id_are_finished = false;

    // Since deleting an animation on the main thread leads to its deletion
    // on the impl thread, we only mark a Finished main thread animation for
    // deletion once it has received a Finished event from the impl thread.
    bool animation_i_will_send_or_has_received_finish_event =
        events || animations_[i]->received_finished_event();
    // If an animation is finished, and not already marked for deletion,
    // find out if all other animations in the same group are also finished.
    if (animations_[i]->run_state() == Animation::Finished &&
        animation_i_will_send_or_has_received_finish_event) {
      // Clear the animations_with_same_group_id if it was added for
      // the previous animation's iteration.
      if (animations_with_same_group_id.size() > 0)
        animations_with_same_group_id.clear();
      all_anims_with_same_id_are_finished = true;
      for (size_t j = 0; j < animations_.size(); ++j) {
        bool animation_j_will_send_or_has_received_finish_event =
            events || animations_[j]->received_finished_event();
        if (group_id == animations_[j]->group()) {
          if (!animations_[j]->is_finished() ||
              (animations_[j]->run_state() == Animation::Finished &&
               !animation_j_will_send_or_has_received_finish_event)) {
            all_anims_with_same_id_are_finished = false;
            break;
          } else if (j >= i &&
                     animations_[j]->run_state() != Animation::Aborted) {
            // Mark down the animations which belong to the same group
            // and is not yet aborted. If this current iteration finds that all
            // animations with same ID are finished, then the marked
            // animations below will be set to WaitingForDeletion in next
            // iteration.
            animations_with_same_group_id.push_back(j);
          }
        }
      }
    }
    if (all_anims_with_same_id_are_finished) {
      // We now need to remove all animations with the same group id as
      // group_id (and send along animation finished notifications, if
      // necessary).
      for (size_t j = 0; j < animations_with_same_group_id.size(); j++) {
        size_t animation_index = animations_with_same_group_id[j];
          if (events) {
            AnimationEvent finished_event(
                AnimationEvent::Finished,
                id_,
                animations_[animation_index]->group(),
                animations_[animation_index]->target_property(),
                monotonic_time);
            finished_event.is_impl_only =
                animations_[animation_index]->is_impl_only();
            if (finished_event.is_impl_only)
              NotifyAnimationFinished(finished_event);
            else
              events->push_back(finished_event);
          }
          animations_[animation_index]->SetRunState(
              Animation::WaitingForDeletion, monotonic_time);
      }
      marked_animations_for_deletions = true;
    }
  }
  if (marked_animations_for_deletions)
    NotifyObserversAnimationWaitingForDeletion();
}

static bool IsWaitingForDeletion(Animation* animation) {
  return animation->run_state() == Animation::WaitingForDeletion;
}

void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
  animations_.erase(cc::remove_if(&animations_,
                                  animations_.begin(),
                                  animations_.end(),
                                  IsWaitingForDeletion),
                    animations_.end());
}

void LayerAnimationController::TickAnimations(base::TimeTicks monotonic_time) {
  for (size_t i = 0; i < animations_.size(); ++i) {
    if (animations_[i]->run_state() == Animation::Starting ||
        animations_[i]->run_state() == Animation::Running ||
        animations_[i]->run_state() == Animation::Paused) {
      if (!animations_[i]->InEffect(monotonic_time))
        continue;

      base::TimeDelta trimmed =
          animations_[i]->TrimTimeToCurrentIteration(monotonic_time);

      switch (animations_[i]->target_property()) {
        case Animation::Transform: {
          const TransformAnimationCurve* transform_animation_curve =
              animations_[i]->curve()->ToTransformAnimationCurve();
          const gfx::Transform transform =
              transform_animation_curve->GetValue(trimmed);
          NotifyObserversTransformAnimated(
              transform,
              animations_[i]->affects_active_observers(),
              animations_[i]->affects_pending_observers());
          break;
        }

        case Animation::Opacity: {
          const FloatAnimationCurve* float_animation_curve =
              animations_[i]->curve()->ToFloatAnimationCurve();
          const float opacity = std::max(
              std::min(float_animation_curve->GetValue(trimmed), 1.0f), 0.f);
          NotifyObserversOpacityAnimated(
              opacity,
              animations_[i]->affects_active_observers(),
              animations_[i]->affects_pending_observers());
          break;
        }

        case Animation::Filter: {
          const FilterAnimationCurve* filter_animation_curve =
              animations_[i]->curve()->ToFilterAnimationCurve();
          const FilterOperations filter =
              filter_animation_curve->GetValue(trimmed);
          NotifyObserversFilterAnimated(
              filter,
              animations_[i]->affects_active_observers(),
              animations_[i]->affects_pending_observers());
          break;
        }

        case Animation::BackgroundColor: {
          // Not yet implemented.
          break;
        }

        case Animation::ScrollOffset: {
          const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
              animations_[i]->curve()->ToScrollOffsetAnimationCurve();
          const gfx::ScrollOffset scroll_offset =
              scroll_offset_animation_curve->GetValue(trimmed);
          NotifyObserversScrollOffsetAnimated(
              scroll_offset,
              animations_[i]->affects_active_observers(),
              animations_[i]->affects_pending_observers());
          break;
        }

        // Do nothing for sentinel value.
        case Animation::TargetPropertyEnumSize:
          NOTREACHED();
      }
    }
  }
}

void LayerAnimationController::UpdateActivation(UpdateActivationType type) {
  bool force = type == ForceActivation;
  if (registrar_) {
    bool was_active = is_active_;
    is_active_ = false;
    for (size_t i = 0; i < animations_.size(); ++i) {
      if (animations_[i]->run_state() != Animation::WaitingForDeletion) {
        is_active_ = true;
        break;
      }
    }

    if (is_active_ && (!was_active || force))
      registrar_->DidActivateAnimationController(this);
    else if (!is_active_ && (was_active || force))
      registrar_->DidDeactivateAnimationController(this);
  }
}

void LayerAnimationController::NotifyObserversOpacityAnimated(
    float opacity,
    bool notify_active_observers,
    bool notify_pending_observers) {
  if (value_observers_.might_have_observers()) {
    ObserverListBase<LayerAnimationValueObserver>::Iterator it(
        value_observers_);
    LayerAnimationValueObserver* obs;
    while ((obs = it.GetNext()) != nullptr) {
      if ((notify_active_observers && notify_pending_observers) ||
          (notify_active_observers && obs->IsActive()) ||
          (notify_pending_observers && !obs->IsActive()))
        obs->OnOpacityAnimated(opacity);
    }
  }
}

void LayerAnimationController::NotifyObserversTransformAnimated(
    const gfx::Transform& transform,
    bool notify_active_observers,
    bool notify_pending_observers) {
  if (value_observers_.might_have_observers()) {
    ObserverListBase<LayerAnimationValueObserver>::Iterator it(
        value_observers_);
    LayerAnimationValueObserver* obs;
    while ((obs = it.GetNext()) != nullptr) {
      if ((notify_active_observers && notify_pending_observers) ||
          (notify_active_observers && obs->IsActive()) ||
          (notify_pending_observers && !obs->IsActive()))
        obs->OnTransformAnimated(transform);
    }
  }
}

void LayerAnimationController::NotifyObserversFilterAnimated(
    const FilterOperations& filters,
    bool notify_active_observers,
    bool notify_pending_observers) {
  if (value_observers_.might_have_observers()) {
    ObserverListBase<LayerAnimationValueObserver>::Iterator it(
        value_observers_);
    LayerAnimationValueObserver* obs;
    while ((obs = it.GetNext()) != nullptr) {
      if ((notify_active_observers && notify_pending_observers) ||
          (notify_active_observers && obs->IsActive()) ||
          (notify_pending_observers && !obs->IsActive()))
        obs->OnFilterAnimated(filters);
    }
  }
}

void LayerAnimationController::NotifyObserversScrollOffsetAnimated(
    const gfx::ScrollOffset& scroll_offset,
    bool notify_active_observers,
    bool notify_pending_observers) {
  if (value_observers_.might_have_observers()) {
    ObserverListBase<LayerAnimationValueObserver>::Iterator it(
        value_observers_);
    LayerAnimationValueObserver* obs;
    while ((obs = it.GetNext()) != nullptr) {
      if ((notify_active_observers && notify_pending_observers) ||
          (notify_active_observers && obs->IsActive()) ||
          (notify_pending_observers && !obs->IsActive()))
        obs->OnScrollOffsetAnimated(scroll_offset);
    }
  }
}

void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() {
  FOR_EACH_OBSERVER(LayerAnimationValueObserver,
                    value_observers_,
                    OnAnimationWaitingForDeletion());
}

bool LayerAnimationController::HasValueObserver() {
  if (value_observers_.might_have_observers()) {
    ObserverListBase<LayerAnimationValueObserver>::Iterator it(
        value_observers_);
    return it.GetNext() != nullptr;
  }
  return false;
}

bool LayerAnimationController::HasActiveValueObserver() {
  if (value_observers_.might_have_observers()) {
    ObserverListBase<LayerAnimationValueObserver>::Iterator it(
        value_observers_);
    LayerAnimationValueObserver* obs;
    while ((obs = it.GetNext()) != nullptr)
      if (obs->IsActive())
        return true;
  }
  return false;
}

}  // namespace cc
