// Copyright 2017 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/keyframe_effect.h"

#include <memory>

#include "base/stl_util.h"
#include "base/time/time.h"
#include "cc/animation/animation.h"
#include "cc/animation/animation_curve.h"
#include "cc/animation/animation_host.h"
#include "cc/animation/keyframe_model.h"
#include "cc/animation/scroll_offset_animation_curve.h"
#include "cc/animation/transform_operations.h"
#include "cc/trees/property_animation_state.h"

namespace cc {

namespace {

bool NeedsFinishedEvent(KeyframeModel* keyframe_model) {
  // The controlling instance (i.e., impl instance), sends the finish event and
  // does not need to receive it.
  if (keyframe_model->is_controlling_instance())
    return false;

  return !keyframe_model->received_finished_event();
}

// Returns indices for keyframe_models that have matching group id.
std::vector<size_t> FindAnimationsWithSameGroupId(
    const std::vector<std::unique_ptr<KeyframeModel>>& keyframe_models,
    int group_id) {
  std::vector<size_t> group;
  for (size_t i = 0; i < keyframe_models.size(); ++i) {
    if (keyframe_models[i]->group() != group_id)
      continue;

    group.push_back(i);
  }
  return group;
}

}  // namespace

KeyframeEffect::KeyframeEffect(KeyframeEffectId id)
    : animation_(),
      id_(id),
      element_animations_(),
      needs_to_start_keyframe_models_(false),
      scroll_offset_animation_was_interrupted_(false),
      is_ticking_(false),
      needs_push_properties_(false) {}

KeyframeEffect::~KeyframeEffect() {
  DCHECK(!has_bound_element_animations());
}

std::unique_ptr<KeyframeEffect> KeyframeEffect::Create(KeyframeEffectId id) {
  return std::make_unique<KeyframeEffect>(id);
}

std::unique_ptr<KeyframeEffect> KeyframeEffect::CreateImplInstance() const {
  return KeyframeEffect::Create(id());
}

void KeyframeEffect::SetNeedsPushProperties() {
  needs_push_properties_ = true;

  // TODO(smcgruer): We only need the below calls when needs_push_properties_
  // goes from false to true - see http://crbug.com/764405
  DCHECK(element_animations());
  element_animations()->SetNeedsPushProperties();

  animation_->SetNeedsPushProperties();
}

void KeyframeEffect::BindElementAnimations(
    ElementAnimations* element_animations) {
  DCHECK(element_animations);
  DCHECK(!element_animations_);
  element_animations_ = element_animations;

  DCHECK(element_id_);
  DCHECK(element_id_ == element_animations->element_id());

  if (has_any_keyframe_model())
    KeyframeModelAdded();
  SetNeedsPushProperties();
}

void KeyframeEffect::UnbindElementAnimations() {
  SetNeedsPushProperties();
  element_animations_ = nullptr;
}

void KeyframeEffect::AttachElement(ElementId element_id) {
  DCHECK(!element_id_);
  DCHECK(element_id);
  element_id_ = element_id;
}

void KeyframeEffect::DetachElement() {
  DCHECK(element_id_);
  element_id_ = ElementId();
}

void KeyframeEffect::Tick(base::TimeTicks monotonic_time) {
  DCHECK(has_bound_element_animations());
  if (!element_animations_->has_element_in_any_list())
    return;

  if (needs_to_start_keyframe_models_)
    StartKeyframeModels(monotonic_time);

  for (auto& keyframe_model : keyframe_models_) {
    TickKeyframeModel(monotonic_time, keyframe_model.get(),
                      element_animations_.get());
  }

  last_tick_time_ = monotonic_time;
  element_animations_->UpdateClientAnimationState();
}

void KeyframeEffect::TickKeyframeModel(base::TimeTicks monotonic_time,
                                       KeyframeModel* keyframe_model,
                                       AnimationTarget* target) {
  if ((keyframe_model->run_state() != KeyframeModel::STARTING &&
       keyframe_model->run_state() != KeyframeModel::RUNNING &&
       keyframe_model->run_state() != KeyframeModel::PAUSED) ||
      !keyframe_model->InEffect(monotonic_time)) {
    return;
  }

  AnimationCurve* curve = keyframe_model->curve();
  base::TimeDelta trimmed =
      keyframe_model->TrimTimeToCurrentIteration(monotonic_time);

  switch (curve->Type()) {
    case AnimationCurve::TRANSFORM:
      target->NotifyClientTransformOperationsAnimated(
          curve->ToTransformAnimationCurve()->GetValue(trimmed),
          keyframe_model->target_property_id(), keyframe_model);
      break;
    case AnimationCurve::FLOAT:
      target->NotifyClientFloatAnimated(
          curve->ToFloatAnimationCurve()->GetValue(trimmed),
          keyframe_model->target_property_id(), keyframe_model);
      break;
    case AnimationCurve::FILTER:
      target->NotifyClientFilterAnimated(
          curve->ToFilterAnimationCurve()->GetValue(trimmed),
          keyframe_model->target_property_id(), keyframe_model);
      break;
    case AnimationCurve::COLOR:
      target->NotifyClientColorAnimated(
          curve->ToColorAnimationCurve()->GetValue(trimmed),
          keyframe_model->target_property_id(), keyframe_model);
      break;
    case AnimationCurve::SCROLL_OFFSET:
      target->NotifyClientScrollOffsetAnimated(
          curve->ToScrollOffsetAnimationCurve()->GetValue(trimmed),
          keyframe_model->target_property_id(), keyframe_model);
      break;
    case AnimationCurve::SIZE:
      target->NotifyClientSizeAnimated(
          curve->ToSizeAnimationCurve()->GetValue(trimmed),
          keyframe_model->target_property_id(), keyframe_model);
      break;
  }
}

void KeyframeEffect::RemoveFromTicking() {
  is_ticking_ = false;
  // Resetting last_tick_time_ here ensures that calling ::UpdateState
  // before ::Animate doesn't start a keyframe model.
  last_tick_time_ = base::TimeTicks();
  animation_->RemoveFromTicking();
}

void KeyframeEffect::UpdateState(bool start_ready_keyframe_models,
                                 AnimationEvents* events) {
  DCHECK(has_bound_element_animations());

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

  if (start_ready_keyframe_models)
    PromoteStartedKeyframeModels(events);

  MarkFinishedKeyframeModels(last_tick_time_);
  MarkKeyframeModelsForDeletion(last_tick_time_, events);
  PurgeKeyframeModelsMarkedForDeletion(/* impl_only */ true);

  if (start_ready_keyframe_models) {
    if (needs_to_start_keyframe_models_) {
      StartKeyframeModels(last_tick_time_);
      PromoteStartedKeyframeModels(events);
    }
  }

  if (!element_animations()->has_element_in_any_list())
    RemoveFromTicking();
}

void KeyframeEffect::UpdateTickingState() {
  if (animation_->has_animation_host()) {
    bool was_ticking = is_ticking_;
    is_ticking_ = HasNonDeletedKeyframeModel() &&
                  element_animations_->has_element_in_any_list();

    if (is_ticking_ && !was_ticking) {
      animation_->AddToTicking();
    } else if (!is_ticking_ && was_ticking) {
      RemoveFromTicking();
    }
  }
}

void KeyframeEffect::Pause(base::TimeDelta pause_offset) {
  for (auto& keyframe_model : keyframe_models_)
    keyframe_model->Pause(pause_offset);

  if (has_bound_element_animations()) {
    animation_->SetNeedsCommit();
    SetNeedsPushProperties();
  }
}

void KeyframeEffect::AddKeyframeModel(
    std::unique_ptr<KeyframeModel> keyframe_model) {
  DCHECK(keyframe_model->target_property_id() !=
             TargetProperty::SCROLL_OFFSET ||
         (animation_->animation_host()->SupportsScrollAnimations()));
  DCHECK(!keyframe_model->is_impl_only() ||
         keyframe_model->target_property_id() == TargetProperty::SCROLL_OFFSET);
  // This is to make sure that keyframe models in the same group, i.e., start
  // together, don't animate the same property.
  DCHECK(std::none_of(
      keyframe_models_.begin(), keyframe_models_.end(),
      [&](const auto& existing_keyframe_model) {
        return keyframe_model->target_property_id() ==
                   existing_keyframe_model->target_property_id() &&
               keyframe_model->group() == existing_keyframe_model->group();
      }));

  keyframe_models_.push_back(std::move(keyframe_model));

  if (has_bound_element_animations()) {
    KeyframeModelAdded();
    SetNeedsPushProperties();
  }
}

void KeyframeEffect::PauseKeyframeModel(int keyframe_model_id,
                                        double time_offset) {
  const base::TimeDelta pause_offset =
      base::TimeDelta::FromSecondsD(time_offset);
  for (auto& keyframe_model : keyframe_models_) {
    if (keyframe_model->id() == keyframe_model_id) {
      keyframe_model->Pause(pause_offset);
    }
  }

  if (has_bound_element_animations()) {
    animation_->SetNeedsCommit();
    SetNeedsPushProperties();
  }
}

void KeyframeEffect::RemoveKeyframeModel(int keyframe_model_id) {
  bool keyframe_model_removed = false;

  // Since we want to use the KeyframeModels that we're going to remove, we
  // need to use a stable_parition here instead of remove_if. Remove_if leaves
  // the removed items in an unspecified state.
  auto keyframe_models_to_remove = std::stable_partition(
      keyframe_models_.begin(), keyframe_models_.end(),
      [keyframe_model_id](
          const std::unique_ptr<KeyframeModel>& keyframe_model) {
        return keyframe_model->id() != keyframe_model_id;
      });
  for (auto it = keyframe_models_to_remove; it != keyframe_models_.end();
       ++it) {
    if ((*it)->target_property_id() == TargetProperty::SCROLL_OFFSET) {
      if (has_bound_element_animations())
        scroll_offset_animation_was_interrupted_ = true;
    } else if (!(*it)->is_finished()) {
      keyframe_model_removed = true;
    }
  }

  keyframe_models_.erase(keyframe_models_to_remove, keyframe_models_.end());

  if (has_bound_element_animations()) {
    UpdateTickingState();
    if (keyframe_model_removed)
      element_animations_->UpdateClientAnimationState();
    animation_->SetNeedsCommit();
    SetNeedsPushProperties();
  }
}

void KeyframeEffect::AbortKeyframeModel(int keyframe_model_id) {
  if (KeyframeModel* keyframe_model = GetKeyframeModelById(keyframe_model_id)) {
    if (!keyframe_model->is_finished()) {
      keyframe_model->SetRunState(KeyframeModel::ABORTED, last_tick_time_);
      if (has_bound_element_animations())
        element_animations_->UpdateClientAnimationState();
    }
  }

  if (has_bound_element_animations()) {
    animation_->SetNeedsCommit();
    SetNeedsPushProperties();
  }
}

void KeyframeEffect::AbortKeyframeModelsWithProperty(
    TargetProperty::Type target_property,
    bool needs_completion) {
  if (needs_completion)
    DCHECK(target_property == TargetProperty::SCROLL_OFFSET);

  bool aborted_keyframe_model = false;
  for (auto& keyframe_model : keyframe_models_) {
    if (keyframe_model->target_property_id() == target_property &&
        !keyframe_model->is_finished()) {
      // Currently only impl-only scroll offset KeyframeModels can be completed
      // on the main thread.
      if (needs_completion && keyframe_model->is_impl_only()) {
        keyframe_model->SetRunState(KeyframeModel::ABORTED_BUT_NEEDS_COMPLETION,
                                    last_tick_time_);
      } else {
        keyframe_model->SetRunState(KeyframeModel::ABORTED, last_tick_time_);
      }
      aborted_keyframe_model = true;
    }
  }

  if (has_bound_element_animations()) {
    if (aborted_keyframe_model)
      element_animations_->UpdateClientAnimationState();
    animation_->SetNeedsCommit();
    SetNeedsPushProperties();
  }
}

void KeyframeEffect::ActivateKeyframeEffects() {
  DCHECK(has_bound_element_animations());

  bool keyframe_model_activated = false;
  for (auto& keyframe_model : keyframe_models_) {
    if (keyframe_model->affects_active_elements() !=
        keyframe_model->affects_pending_elements()) {
      keyframe_model_activated = true;
    }
    keyframe_model->set_affects_active_elements(
        keyframe_model->affects_pending_elements());
  }

  if (keyframe_model_activated)
    element_animations_->UpdateClientAnimationState();

  scroll_offset_animation_was_interrupted_ = false;
}

void KeyframeEffect::KeyframeModelAdded() {
  DCHECK(has_bound_element_animations());

  animation_->SetNeedsCommit();
  needs_to_start_keyframe_models_ = true;

  UpdateTickingState();
  element_animations_->UpdateClientAnimationState();
}

bool KeyframeEffect::NotifyKeyframeModelStarted(const AnimationEvent& event) {
  DCHECK(!event.is_impl_only);
  for (auto& keyframe_model : keyframe_models_) {
    if (keyframe_model->group() == event.group_id &&
        keyframe_model->target_property_id() == event.target_property &&
        keyframe_model->needs_synchronized_start_time()) {
      keyframe_model->set_needs_synchronized_start_time(false);
      if (!keyframe_model->has_set_start_time())
        keyframe_model->set_start_time(event.monotonic_time);
      animation_->NotifyKeyframeModelStarted(event);
      return true;
    }
  }
  return false;
}

bool KeyframeEffect::NotifyKeyframeModelFinished(const AnimationEvent& event) {
  DCHECK(!event.is_impl_only);
  for (auto& keyframe_model : keyframe_models_) {
    if (keyframe_model->group() == event.group_id &&
        keyframe_model->target_property_id() == event.target_property) {
      keyframe_model->set_received_finished_event(true);
      animation_->NotifyKeyframeModelFinished(event);
      return true;
    }
  }

  // This is for the case when a keyframe_model is already removed on main
  // thread, but the impl version of it sent a finished event and is now waiting
  // for deletion. We would need to delete that keyframe_model during push
  // properties.
  SetNeedsPushProperties();
  return false;
}

void KeyframeEffect::NotifyKeyframeModelTakeover(const AnimationEvent& event) {
  DCHECK(!event.is_impl_only);

  // We need to purge KeyframeModels marked for deletion on CT.
  SetNeedsPushProperties();

  animation_->NotifyKeyframeModelTakeover(event);
}

bool KeyframeEffect::NotifyKeyframeModelAborted(const AnimationEvent& event) {
  DCHECK(!event.is_impl_only);
  for (auto& keyframe_model : keyframe_models_) {
    if (keyframe_model->group() == event.group_id &&
        keyframe_model->target_property_id() == event.target_property) {
      keyframe_model->SetRunState(KeyframeModel::ABORTED, event.monotonic_time);
      keyframe_model->set_received_finished_event(true);
      animation_->NotifyKeyframeModelAborted(event);
      return true;
    }
  }
  return false;
}

bool KeyframeEffect::HasTickingKeyframeModel() const {
  for (const auto& keyframe_model : keyframe_models_) {
    if (!keyframe_model->is_finished())
      return true;
  }
  return false;
}

size_t KeyframeEffect::TickingKeyframeModelsCount() const {
  size_t ticking_keyframe_models_count = 0;
  for (const auto& it : keyframe_models_)
    if (!it->is_finished())
      ticking_keyframe_models_count++;
  return ticking_keyframe_models_count;
}

bool KeyframeEffect::HasNonDeletedKeyframeModel() const {
  for (const auto& keyframe_model : keyframe_models_) {
    if (keyframe_model->run_state() != KeyframeModel::WAITING_FOR_DELETION)
      return true;
  }
  return false;
}

bool KeyframeEffect::AnimationsPreserveAxisAlignment() const {
  for (const auto& keyframe_model : keyframe_models_) {
    if (keyframe_model->is_finished() ||
        keyframe_model->target_property_id() != TargetProperty::TRANSFORM)
      continue;

    const TransformAnimationCurve* transform_animation_curve =
        keyframe_model->curve()->ToTransformAnimationCurve();
    if (!transform_animation_curve->PreservesAxisAlignment())
      return false;
  }
  return true;
}

bool KeyframeEffect::GetAnimationScales(ElementListType list_type,
                                        float* maximum_scale,
                                        float* starting_scale) const {
  *maximum_scale = kNotScaled;
  *starting_scale = kNotScaled;
  bool maximum_scale_valid = true;
  bool starting_scale_valid = true;
  for (const auto& keyframe_model : keyframe_models_) {
    if (keyframe_model->is_finished() ||
        keyframe_model->target_property_id() != TargetProperty::TRANSFORM)
      continue;

    if ((list_type == ElementListType::ACTIVE &&
         !keyframe_model->affects_active_elements()) ||
        (list_type == ElementListType::PENDING &&
         !keyframe_model->affects_pending_elements()))
      continue;

    const TransformAnimationCurve* transform_animation_curve =
        keyframe_model->curve()->ToTransformAnimationCurve();
    if (transform_animation_curve->IsTranslation())
      continue;

    bool forward_direction = true;
    switch (keyframe_model->direction()) {
      case KeyframeModel::Direction::NORMAL:
      case KeyframeModel::Direction::ALTERNATE_NORMAL:
        forward_direction = keyframe_model->playback_rate() >= 0.0;
        break;
      case KeyframeModel::Direction::REVERSE:
      case KeyframeModel::Direction::ALTERNATE_REVERSE:
        forward_direction = keyframe_model->playback_rate() < 0.0;
        break;
    }

    if (maximum_scale_valid) {
      float keyframe_model_maximum_scale = kNotScaled;
      if (transform_animation_curve->MaximumTargetScale(
              forward_direction, &keyframe_model_maximum_scale)) {
        *maximum_scale = std::max(*maximum_scale, keyframe_model_maximum_scale);
      } else {
        maximum_scale_valid = false;
        *maximum_scale = kNotScaled;
      }
    }

    if (starting_scale_valid) {
      float keyframe_model_starting_scale = kNotScaled;
      if (transform_animation_curve->AnimationStartScale(
              forward_direction, &keyframe_model_starting_scale)) {
        *starting_scale =
            std::max(*starting_scale, keyframe_model_starting_scale);
      } else {
        starting_scale_valid = false;
        *starting_scale = kNotScaled;
      }
    }

    if (!maximum_scale_valid && !starting_scale_valid)
      return false;
  }
  return true;
}

bool KeyframeEffect::IsPotentiallyAnimatingProperty(
    TargetProperty::Type target_property,
    ElementListType list_type) const {
  for (const auto& keyframe_model : keyframe_models_) {
    if (!keyframe_model->is_finished() &&
        keyframe_model->target_property_id() == target_property) {
      if ((list_type == ElementListType::ACTIVE &&
           keyframe_model->affects_active_elements()) ||
          (list_type == ElementListType::PENDING &&
           keyframe_model->affects_pending_elements()))
        return true;
    }
  }
  return false;
}

bool KeyframeEffect::IsCurrentlyAnimatingProperty(
    TargetProperty::Type target_property,
    ElementListType list_type) const {
  for (const auto& keyframe_model : keyframe_models_) {
    if (!keyframe_model->is_finished() &&
        keyframe_model->InEffect(last_tick_time_) &&
        keyframe_model->target_property_id() == target_property) {
      if ((list_type == ElementListType::ACTIVE &&
           keyframe_model->affects_active_elements()) ||
          (list_type == ElementListType::PENDING &&
           keyframe_model->affects_pending_elements()))
        return true;
    }
  }
  return false;
}

KeyframeModel* KeyframeEffect::GetKeyframeModel(
    TargetProperty::Type target_property) const {
  for (size_t i = 0; i < keyframe_models_.size(); ++i) {
    size_t index = keyframe_models_.size() - i - 1;
    if (keyframe_models_[index]->target_property_id() == target_property)
      return keyframe_models_[index].get();
  }
  return nullptr;
}

KeyframeModel* KeyframeEffect::GetKeyframeModelById(
    int keyframe_model_id) const {
  for (auto& keyframe_model : keyframe_models_)
    if (keyframe_model->id() == keyframe_model_id)
      return keyframe_model.get();
  return nullptr;
}

void KeyframeEffect::GetPropertyAnimationState(
    PropertyAnimationState* pending_state,
    PropertyAnimationState* active_state) const {
  pending_state->Clear();
  active_state->Clear();

  for (const auto& keyframe_model : keyframe_models_) {
    if (!keyframe_model->is_finished()) {
      bool in_effect = keyframe_model->InEffect(last_tick_time_);
      bool active = keyframe_model->affects_active_elements();
      bool pending = keyframe_model->affects_pending_elements();
      int property = keyframe_model->target_property_id();

      if (pending)
        pending_state->potentially_animating[property] = true;
      if (pending && in_effect)
        pending_state->currently_running[property] = true;

      if (active)
        active_state->potentially_animating[property] = true;
      if (active && in_effect)
        active_state->currently_running[property] = true;
    }
  }
}

void KeyframeEffect::MarkAbortedKeyframeModelsForDeletion(
    KeyframeEffect* keyframe_effect_impl) {
  bool keyframe_model_aborted = false;

  auto& keyframe_models_impl = keyframe_effect_impl->keyframe_models_;
  for (const auto& keyframe_model_impl : keyframe_models_impl) {
    // If the keyframe_model has been aborted on the main thread, mark it for
    // deletion.
    if (KeyframeModel* keyframe_model =
            GetKeyframeModelById(keyframe_model_impl->id())) {
      if (keyframe_model->run_state() == KeyframeModel::ABORTED) {
        keyframe_model_impl->SetRunState(KeyframeModel::WAITING_FOR_DELETION,
                                         keyframe_effect_impl->last_tick_time_);
        keyframe_model->SetRunState(KeyframeModel::WAITING_FOR_DELETION,
                                    last_tick_time_);
        keyframe_model_aborted = true;
      }
    }
  }

  if (has_bound_element_animations() && keyframe_model_aborted)
    element_animations_->SetNeedsPushProperties();
}

void KeyframeEffect::PurgeKeyframeModelsMarkedForDeletion(bool impl_only) {
  base::EraseIf(
      keyframe_models_,
      [impl_only](const std::unique_ptr<KeyframeModel>& keyframe_model) {
        return keyframe_model->run_state() ==
                   KeyframeModel::WAITING_FOR_DELETION &&
               (!impl_only || keyframe_model->is_impl_only());
      });
}

void KeyframeEffect::PushNewKeyframeModelsToImplThread(
    KeyframeEffect* keyframe_effect_impl) const {
  // Any new KeyframeModels owned by the main thread's Animation are
  // cloned and added to the impl thread's Animation.
  for (const auto& keyframe_model : keyframe_models_) {
    // If the keyframe_model is finished, do not copy it over to impl since the
    // impl instance, if there was one, was just removed in
    // |RemoveKeyframeModelsCompletedOnMainThread|.
    if (keyframe_model->is_finished())
      continue;
    // If the keyframe_model is already running on the impl thread, there is no
    // need to copy it over.
    if (keyframe_effect_impl->GetKeyframeModelById(keyframe_model->id()))
      continue;

    if (keyframe_model->target_property_id() == TargetProperty::SCROLL_OFFSET &&
        !keyframe_model->curve()
             ->ToScrollOffsetAnimationCurve()
             ->HasSetInitialValue()) {
      gfx::ScrollOffset current_scroll_offset;
      if (keyframe_effect_impl->HasElementInActiveList()) {
        current_scroll_offset =
            keyframe_effect_impl->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 = ScrollOffsetForAnimation();
      }
      keyframe_model->curve()->ToScrollOffsetAnimationCurve()->SetInitialValue(
          current_scroll_offset);
    }

    // The new keyframe_model should be set to run as soon as possible.
    KeyframeModel::RunState initial_run_state =
        KeyframeModel::WAITING_FOR_TARGET_AVAILABILITY;
    std::unique_ptr<KeyframeModel> to_add(
        keyframe_model->CreateImplInstance(initial_run_state));
    DCHECK(!to_add->needs_synchronized_start_time());
    to_add->set_affects_active_elements(false);
    keyframe_effect_impl->AddKeyframeModel(std::move(to_add));
  }
}

namespace {
bool IsCompleted(KeyframeModel* keyframe_model,
                 const KeyframeEffect* main_thread_keyframe_effect) {
  if (keyframe_model->is_impl_only()) {
    return (keyframe_model->run_state() == KeyframeModel::WAITING_FOR_DELETION);
  } else {
    KeyframeModel* main_thread_keyframe_model =
        main_thread_keyframe_effect->GetKeyframeModelById(keyframe_model->id());
    return !main_thread_keyframe_model ||
           main_thread_keyframe_model->is_finished();
  }
}
}  // namespace

void KeyframeEffect::RemoveKeyframeModelsCompletedOnMainThread(
    KeyframeEffect* keyframe_effect_impl) const {
  bool keyframe_model_completed = false;

  // Animations removed on the main thread should no longer affect pending
  // elements, and should stop affecting active elements after the next call
  // to ActivateKeyframeEffects. If already WAITING_FOR_DELETION, they can be
  // removed immediately.
  auto& keyframe_models = keyframe_effect_impl->keyframe_models_;
  for (const auto& keyframe_model : keyframe_models) {
    if (IsCompleted(keyframe_model.get(), this)) {
      keyframe_model->set_affects_pending_elements(false);
      keyframe_model_completed = true;
    }
  }
  auto affects_active_only_and_is_waiting_for_deletion =
      [](const std::unique_ptr<KeyframeModel>& keyframe_model) {
        return keyframe_model->run_state() ==
                   KeyframeModel::WAITING_FOR_DELETION &&
               !keyframe_model->affects_pending_elements();
      };
  base::EraseIf(keyframe_models,
                affects_active_only_and_is_waiting_for_deletion);

  if (has_bound_element_animations() && keyframe_model_completed)
    element_animations_->SetNeedsPushProperties();
}

void KeyframeEffect::PushPropertiesTo(KeyframeEffect* keyframe_effect_impl) {
  if (!needs_push_properties_)
    return;
  needs_push_properties_ = false;

  // Synchronize the keyframe_model target between main and impl side.
  if (element_id_ != keyframe_effect_impl->element_id_) {
    // We have to detach/attach via the Animation as it may need to inform
    // the host as well.
    if (keyframe_effect_impl->has_attached_element()) {
      keyframe_effect_impl->animation_->DetachElementForKeyframeEffect(
          keyframe_effect_impl->element_id_, keyframe_effect_impl->id_);
    }
    if (element_id_) {
      keyframe_effect_impl->animation_->AttachElementForKeyframeEffect(
          element_id_, id_);
    }
  }

  // If neither main nor impl have any KeyframeModels, there is nothing further
  // to synchronize.
  if (!has_any_keyframe_model() &&
      !keyframe_effect_impl->has_any_keyframe_model())
    return;

  // Synchronize the main-thread and impl-side keyframe model lists, removing
  // aborted KeyframeModels and pushing any new animations.
  MarkAbortedKeyframeModelsForDeletion(keyframe_effect_impl);
  PurgeKeyframeModelsMarkedForDeletion(/* impl_only */ false);
  RemoveKeyframeModelsCompletedOnMainThread(keyframe_effect_impl);
  PushNewKeyframeModelsToImplThread(keyframe_effect_impl);

  // Now that the keyframe model lists are synchronized, push the properties for
  // the individual KeyframeModels.
  for (const auto& keyframe_model : keyframe_models_) {
    KeyframeModel* current_impl =
        keyframe_effect_impl->GetKeyframeModelById(keyframe_model->id());
    if (current_impl)
      keyframe_model->PushPropertiesTo(current_impl);
  }
  keyframe_effect_impl->scroll_offset_animation_was_interrupted_ =
      scroll_offset_animation_was_interrupted_;
  scroll_offset_animation_was_interrupted_ = false;

  keyframe_effect_impl->UpdateTickingState();
}

void KeyframeEffect::SetAnimation(Animation* animation) {
  animation_ = animation;
}

std::string KeyframeEffect::KeyframeModelsToString() const {
  std::string str;
  for (size_t i = 0; i < keyframe_models_.size(); i++) {
    if (i > 0)
      str.append(", ");
    str.append(keyframe_models_[i]->ToString());
  }
  return str;
}

void KeyframeEffect::StartKeyframeModels(base::TimeTicks monotonic_time) {
  DCHECK(needs_to_start_keyframe_models_);
  needs_to_start_keyframe_models_ = false;

  // First collect running properties affecting each type of element.
  TargetProperties blocked_properties_for_active_elements;
  TargetProperties blocked_properties_for_pending_elements;
  std::vector<size_t> keyframe_models_waiting_for_target;

  keyframe_models_waiting_for_target.reserve(keyframe_models_.size());
  for (size_t i = 0; i < keyframe_models_.size(); ++i) {
    auto& keyframe_model = keyframe_models_[i];
    if (keyframe_model->run_state() == KeyframeModel::STARTING ||
        keyframe_model->run_state() == KeyframeModel::RUNNING) {
      int property = keyframe_model->target_property_id();
      if (keyframe_model->affects_active_elements()) {
        blocked_properties_for_active_elements[property] = true;
      }
      if (keyframe_model->affects_pending_elements()) {
        blocked_properties_for_pending_elements[property] = true;
      }
    } else if (keyframe_model->run_state() ==
               KeyframeModel::WAITING_FOR_TARGET_AVAILABILITY) {
      keyframe_models_waiting_for_target.push_back(i);
    }
  }

  for (size_t i = 0; i < keyframe_models_waiting_for_target.size(); ++i) {
    // Collect all properties for KeyframeModels with the same group id (they
    // should all also be in the list of KeyframeModels).
    size_t keyframe_model_index = keyframe_models_waiting_for_target[i];
    KeyframeModel* keyframe_model_waiting_for_target =
        keyframe_models_[keyframe_model_index].get();
    // Check for the run state again even though the keyframe_model was waiting
    // for target because it might have changed the run state while handling
    // previous keyframe_model in this loop (if they belong to same group).
    if (keyframe_model_waiting_for_target->run_state() ==
        KeyframeModel::WAITING_FOR_TARGET_AVAILABILITY) {
      TargetProperties enqueued_properties;
      bool affects_active_elements =
          keyframe_model_waiting_for_target->affects_active_elements();
      bool affects_pending_elements =
          keyframe_model_waiting_for_target->affects_pending_elements();
      enqueued_properties[keyframe_model_waiting_for_target
                              ->target_property_id()] = true;
      for (size_t j = keyframe_model_index + 1; j < keyframe_models_.size();
           ++j) {
        if (keyframe_model_waiting_for_target->group() ==
            keyframe_models_[j]->group()) {
          enqueued_properties[keyframe_models_[j]->target_property_id()] = true;
          affects_active_elements |=
              keyframe_models_[j]->affects_active_elements();
          affects_pending_elements |=
              keyframe_models_[j]->affects_pending_elements();
        }
      }

      // 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 elements 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 (int property = TargetProperty::FIRST_TARGET_PROPERTY;
           property <= TargetProperty::LAST_TARGET_PROPERTY; ++property) {
        if (enqueued_properties[property]) {
          if (affects_active_elements) {
            if (blocked_properties_for_active_elements[property])
              null_intersection = false;
            else
              blocked_properties_for_active_elements[property] = true;
          }
          if (affects_pending_elements) {
            if (blocked_properties_for_pending_elements[property])
              null_intersection = false;
            else
              blocked_properties_for_pending_elements[property] = true;
          }
        }
      }

      // If the intersection is null, then we are free to start the
      // KeyframeModels in the group.
      if (null_intersection) {
        keyframe_model_waiting_for_target->SetRunState(KeyframeModel::STARTING,
                                                       monotonic_time);
        for (size_t j = keyframe_model_index + 1; j < keyframe_models_.size();
             ++j) {
          if (keyframe_model_waiting_for_target->group() ==
              keyframe_models_[j]->group()) {
            keyframe_models_[j]->SetRunState(KeyframeModel::STARTING,
                                             monotonic_time);
          }
        }
      } else {
        needs_to_start_keyframe_models_ = true;
      }
    }
  }
}

void KeyframeEffect::PromoteStartedKeyframeModels(AnimationEvents* events) {
  for (auto& keyframe_model : keyframe_models_) {
    if (keyframe_model->run_state() == KeyframeModel::STARTING &&
        keyframe_model->affects_active_elements()) {
      keyframe_model->SetRunState(KeyframeModel::RUNNING, last_tick_time_);
      if (!keyframe_model->has_set_start_time() &&
          !keyframe_model->needs_synchronized_start_time())
        keyframe_model->set_start_time(last_tick_time_);

      base::TimeTicks start_time;
      if (keyframe_model->has_set_start_time())
        start_time = keyframe_model->start_time();
      else
        start_time = last_tick_time_;

      GenerateEvent(events, *keyframe_model, AnimationEvent::STARTED,
                    start_time);
    }
  }
}

void KeyframeEffect::MarkKeyframeModelsForDeletion(
    base::TimeTicks monotonic_time,
    AnimationEvents* events) {
  bool marked_keyframe_model_for_deletion = false;
  auto MarkForDeletion = [&](KeyframeModel* keyframe_model) {
    keyframe_model->SetRunState(KeyframeModel::WAITING_FOR_DELETION,
                                monotonic_time);
    marked_keyframe_model_for_deletion = true;
  };

  // Non-aborted KeyframeModels 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
  // KeyframeModels have received a finished event before marking them for
  // deletion.
  for (size_t i = 0; i < keyframe_models_.size(); i++) {
    KeyframeModel* keyframe_model = keyframe_models_[i].get();
    if (keyframe_model->run_state() == KeyframeModel::ABORTED) {
      GenerateEvent(events, *keyframe_model, AnimationEvent::ABORTED,
                    monotonic_time);
      // If this is the controlling instance or it has already received finish
      // event, keyframe model can be marked for deletion.
      if (!NeedsFinishedEvent(keyframe_model))
        MarkForDeletion(keyframe_model);
      continue;
    }

    // If this is an aborted controlling instance that need completion on the
    // main thread, generate takeover event.
    if (keyframe_model->is_controlling_instance() &&
        keyframe_model->run_state() ==
            KeyframeModel::ABORTED_BUT_NEEDS_COMPLETION) {
      GenerateTakeoverEventForScrollAnimation(events, *keyframe_model,
                                              monotonic_time);
      // Remove the keyframe model from the impl thread.
      MarkForDeletion(keyframe_model);
      continue;
    }

    if (keyframe_model->run_state() != KeyframeModel::FINISHED)
      continue;

    // 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.
    if (NeedsFinishedEvent(keyframe_model))
      continue;

    // If a keyframe model is finished, and not already marked for deletion,
    // find out if all other keyframe models in the same group are also
    // finished.
    std::vector<size_t> keyframe_models_in_same_group =
        FindAnimationsWithSameGroupId(keyframe_models_,
                                      keyframe_model->group());

    bool a_keyframe_model_in_same_group_is_not_finished = std::any_of(
        keyframe_models_in_same_group.cbegin(),
        keyframe_models_in_same_group.cend(), [&](size_t index) {
          KeyframeModel* keyframe_model = keyframe_models_[index].get();
          return !keyframe_model->is_finished() ||
                 (keyframe_model->run_state() == KeyframeModel::FINISHED &&
                  NeedsFinishedEvent(keyframe_model));
        });

    if (a_keyframe_model_in_same_group_is_not_finished)
      continue;

    // Now remove all the keyframe models which belong to the same group and are
    // not yet aborted. These will be set to WAITING_FOR_DELETION which also
    // ensures we don't try to delete them again.
    for (size_t j = 0; j < keyframe_models_in_same_group.size(); ++j) {
      KeyframeModel* keyframe_model =
          keyframe_models_[keyframe_models_in_same_group[j]].get();

      // Skip any keyframe model in this group which is already processed.
      if (keyframe_model->run_state() == KeyframeModel::WAITING_FOR_DELETION ||
          keyframe_model->run_state() == KeyframeModel::ABORTED)
        continue;

      GenerateEvent(events, *keyframe_model, AnimationEvent::FINISHED,
                    monotonic_time);
      MarkForDeletion(keyframe_model);
    }
  }

  // We need to purge KeyframeModels marked for deletion, which happens in
  // PushPropertiesTo().
  if (marked_keyframe_model_for_deletion)
    SetNeedsPushProperties();
}

void KeyframeEffect::MarkFinishedKeyframeModels(
    base::TimeTicks monotonic_time) {
  DCHECK(has_bound_element_animations());

  bool keyframe_model_finished = false;
  for (auto& keyframe_model : keyframe_models_) {
    if (!keyframe_model->is_finished() &&
        keyframe_model->IsFinishedAt(monotonic_time)) {
      keyframe_model->SetRunState(KeyframeModel::FINISHED, monotonic_time);
      keyframe_model_finished = true;
      SetNeedsPushProperties();
    }
    if (!keyframe_model->affects_active_elements() &&
        !keyframe_model->affects_pending_elements()) {
      switch (keyframe_model->run_state()) {
        case KeyframeModel::WAITING_FOR_TARGET_AVAILABILITY:
        case KeyframeModel::STARTING:
        case KeyframeModel::RUNNING:
        case KeyframeModel::PAUSED:
          keyframe_model->SetRunState(KeyframeModel::FINISHED, monotonic_time);
          keyframe_model_finished = true;
          break;
        default:
          break;
      }
    }
  }
  if (keyframe_model_finished)
    element_animations_->UpdateClientAnimationState();
}

bool KeyframeEffect::HasElementInActiveList() const {
  DCHECK(has_bound_element_animations());
  return element_animations_->has_element_in_active_list();
}

gfx::ScrollOffset KeyframeEffect::ScrollOffsetForAnimation() const {
  DCHECK(has_bound_element_animations());
  return element_animations_->ScrollOffsetForAnimation();
}

void KeyframeEffect::GenerateEvent(AnimationEvents* events,
                                   const KeyframeModel& keyframe_model,
                                   AnimationEvent::Type type,
                                   base::TimeTicks monotonic_time) {
  if (!events)
    return;

  AnimationEvent event(type, element_id_, keyframe_model.group(),
                       keyframe_model.target_property_id(), monotonic_time);
  event.is_impl_only = keyframe_model.is_impl_only();
  if (!event.is_impl_only) {
    events->events_.push_back(event);
    return;
  }
  // For impl only animations notify delegate directly, do not record the event.
  switch (type) {
    case AnimationEvent::FINISHED:
      animation_->NotifyKeyframeModelFinished(event);
      break;
    case AnimationEvent::STARTED:
      animation_->NotifyKeyframeModelStarted(event);
      break;
    case AnimationEvent::ABORTED:
      animation_->NotifyKeyframeModelAborted(event);
      break;
    case AnimationEvent::TAKEOVER:
      // We never expect to receive a TAKEOVER notification on impl only
      // animations.
      NOTREACHED();
      break;
  }
}

void KeyframeEffect::GenerateTakeoverEventForScrollAnimation(
    AnimationEvents* events,
    const KeyframeModel& keyframe_model,
    base::TimeTicks monotonic_time) {
  DCHECK_EQ(keyframe_model.target_property_id(), TargetProperty::SCROLL_OFFSET);
  if (!events)
    return;

  AnimationEvent takeover_event(
      AnimationEvent::TAKEOVER, element_id_, keyframe_model.group(),
      keyframe_model.target_property_id(), monotonic_time);
  takeover_event.animation_start_time = keyframe_model.start_time();
  const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
      keyframe_model.curve()->ToScrollOffsetAnimationCurve();
  takeover_event.curve = scroll_offset_animation_curve->Clone();
  // Notify the compositor that the animation is finished.
  animation_->NotifyKeyframeModelFinished(takeover_event);
  // Notify main thread.
  events->events_.push_back(takeover_event);
}

}  // namespace cc
