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

#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/trace_event.h"
#include "cc/paint/image_animation_count.h"

namespace cc {
namespace {

// The maximum number of time an animation can be delayed before it is reset to
// start from the beginning, instead of fast-forwarding to catch up to the
// desired frame.
const base::TimeDelta kAnimationResyncCutoff = base::TimeDelta::FromMinutes(5);

}  //  namespace

ImageAnimationController::ImageAnimationController(
    base::SingleThreadTaskRunner* task_runner,
    base::RepeatingClosure invalidation_callback,
    bool enable_image_animation_resync)
    : notifier_(task_runner, invalidation_callback),
      enable_image_animation_resync_(enable_image_animation_resync) {}

ImageAnimationController::~ImageAnimationController() = default;

void ImageAnimationController::UpdateAnimatedImage(
    const DiscardableImageMap::AnimatedImageMetadata& data) {
  AnimationState& animation_state = animation_state_map_[data.paint_image_id];
  animation_state.UpdateMetadata(data);
}

void ImageAnimationController::RegisterAnimationDriver(
    PaintImage::Id paint_image_id,
    AnimationDriver* driver) {
  auto it = animation_state_map_.find(paint_image_id);
  DCHECK(it != animation_state_map_.end());
  it->second.AddDriver(driver);
  registered_animations_.insert(paint_image_id);
}

void ImageAnimationController::UnregisterAnimationDriver(
    PaintImage::Id paint_image_id,
    AnimationDriver* driver) {
  auto it = animation_state_map_.find(paint_image_id);
  DCHECK(it != animation_state_map_.end());
  it->second.RemoveDriver(driver);
  if (!it->second.has_drivers())
    registered_animations_.erase(paint_image_id);
}

const PaintImageIdFlatSet& ImageAnimationController::AnimateForSyncTree(
    base::TimeTicks now) {
  TRACE_EVENT0("cc", "ImageAnimationController::AnimateImagesForSyncTree");
  DCHECK(images_animated_on_sync_tree_.empty());

  notifier_.WillAnimate();
  base::Optional<base::TimeTicks> next_invalidation_time;

  for (auto id : registered_animations_) {
    auto it = animation_state_map_.find(id);
    DCHECK(it != animation_state_map_.end());
    AnimationState& state = it->second;

    // Is anyone still interested in animating this image?
    state.UpdateStateFromDrivers();
    if (!state.ShouldAnimate())
      continue;

    // If we were able to advance this animation, invalidate it on the sync
    // tree.
    if (state.AdvanceFrame(now, enable_image_animation_resync_))
      images_animated_on_sync_tree_.insert(id);

    // Update the next invalidation time to the earliest time at which we need
    // a frame to animate an image.
    // Note its important to check ShouldAnimate() here again since advancing to
    // a new frame on the sync tree means we might not need to animate this
    // image any longer.
    if (!state.ShouldAnimate())
      continue;

    DCHECK_GT(state.next_desired_frame_time(), now);
    if (!next_invalidation_time.has_value()) {
      next_invalidation_time.emplace(state.next_desired_frame_time());
    } else {
      next_invalidation_time = std::min(state.next_desired_frame_time(),
                                        next_invalidation_time.value());
    }
  }

  if (next_invalidation_time.has_value())
    notifier_.Schedule(now, next_invalidation_time.value());
  else
    notifier_.Cancel();

  return images_animated_on_sync_tree_;
}

void ImageAnimationController::UpdateStateFromDrivers(base::TimeTicks now) {
  TRACE_EVENT0("cc", "UpdateStateFromAnimationDrivers");

  base::Optional<base::TimeTicks> next_invalidation_time;
  for (auto image_id : registered_animations_) {
    auto it = animation_state_map_.find(image_id);
    DCHECK(it != animation_state_map_.end());
    AnimationState& state = it->second;
    state.UpdateStateFromDrivers();

    // Note that by not updating the |next_invalidation_time| from this image
    // here, we will cancel any pending invalidation scheduled for this image
    // when updating the |notifier_| at the end of this loop.
    if (!state.ShouldAnimate())
      continue;

    if (!next_invalidation_time.has_value()) {
      next_invalidation_time.emplace(state.next_desired_frame_time());
    } else {
      next_invalidation_time = std::min(next_invalidation_time.value(),
                                        state.next_desired_frame_time());
    }
  }

  if (next_invalidation_time.has_value())
    notifier_.Schedule(now, next_invalidation_time.value());
  else
    notifier_.Cancel();
}

void ImageAnimationController::DidActivate() {
  TRACE_EVENT0("cc", "ImageAnimationController::WillActivate");

  for (auto id : images_animated_on_sync_tree_) {
    auto it = animation_state_map_.find(id);
    DCHECK(it != animation_state_map_.end());
    it->second.PushPendingToActive();
  }
  images_animated_on_sync_tree_.clear();

  // We would retain state for images with no drivers (no recordings) to allow
  // resuming of animations. However, since the animation will be re-started
  // from the beginning after navigation, we can avoid maintaining the state.
  if (did_navigate_) {
    for (auto it = animation_state_map_.begin();
         it != animation_state_map_.end();) {
      if (it->second.has_drivers())
        it++;
      else
        it = animation_state_map_.erase(it);
    }
    did_navigate_ = false;
  }
}

size_t ImageAnimationController::GetFrameIndexForImage(
    PaintImage::Id paint_image_id,
    WhichTree tree) const {
  const auto& it = animation_state_map_.find(paint_image_id);
  DCHECK(it != animation_state_map_.end());
  return tree == WhichTree::PENDING_TREE ? it->second.pending_index()
                                         : it->second.active_index();
}

const base::flat_set<ImageAnimationController::AnimationDriver*>&
ImageAnimationController::GetDriversForTesting(
    PaintImage::Id paint_image_id) const {
  const auto& it = animation_state_map_.find(paint_image_id);
  DCHECK(it != animation_state_map_.end());
  return it->second.drivers_for_testing();
}

size_t ImageAnimationController::GetLastNumOfFramesSkippedForTesting(
    PaintImage::Id paint_image_id) const {
  const auto& it = animation_state_map_.find(paint_image_id);
  DCHECK(it != animation_state_map_.end());
  return it->second.last_num_frames_skipped_for_testing();
}

ImageAnimationController::AnimationState::AnimationState() = default;

ImageAnimationController::AnimationState::AnimationState(
    AnimationState&& other) = default;

ImageAnimationController::AnimationState&
ImageAnimationController::AnimationState::operator=(AnimationState&& other) =
    default;

ImageAnimationController::AnimationState::~AnimationState() {
  DCHECK(drivers_.empty());
}

bool ImageAnimationController::AnimationState::ShouldAnimate() const {
  DCHECK(repetitions_completed_ == 0 || is_complete());

  // If we have no drivers for this image, no need to animate it.
  if (!should_animate_from_drivers_)
    return false;

  switch (requested_repetitions_) {
    case kAnimationLoopOnce:
      if (repetitions_completed_ >= 1)
        return false;
      break;
    case kAnimationNone:
      NOTREACHED() << "We shouldn't be tracking kAnimationNone images";
      break;
    case kAnimationLoopInfinite:
      break;
    default:
      if (requested_repetitions_ <= repetitions_completed_)
        return false;
  }

  // If we have not yet received all data for this image, we can not advance to
  // an incomplete frame.
  if (!frames_[NextFrameIndex()].complete)
    return false;

  // If we don't have all data for this image, we can not trust the frame count
  // and loop back to the first frame.
  size_t last_frame_index = frames_.size() - 1;
  if (completion_state_ != PaintImage::CompletionState::DONE &&
      pending_index_ == last_frame_index)
    return false;

  return true;
}

bool ImageAnimationController::AnimationState::AdvanceFrame(
    base::TimeTicks now,
    bool enable_image_animation_resync) {
  DCHECK(ShouldAnimate());

  // Start the animation from the first frame, if not yet started. We don't need
  // an invalidation here if the pending and active tree are both displaying the
  // first frame. Its possible for the 2 to be different if the animation was
  // reset, in which case we are starting again from the first frame on the
  // pending tree.
  if (!animation_started_) {
    DCHECK_EQ(pending_index_, 0u);

    next_desired_frame_time_ = now + frames_[0].duration;
    animation_started_ = true;
    return pending_index_ != active_index_;
  }

  // Don't advance the animation if its not time yet to move to the next frame.
  if (now < next_desired_frame_time_)
    return false;

  // If the animation is more than 5 min out of date, we don't bother catching
  // up and start again from the current frame.
  // Note that we don't need to invalidate this image since the active tree
  // is already displaying the current frame.
  if (enable_image_animation_resync &&
      now - next_desired_frame_time_ > kAnimationResyncCutoff) {
    DCHECK_EQ(pending_index_, active_index_);
    next_desired_frame_time_ = now + frames_[pending_index_].duration;
    return false;
  }

  // Keep catching up the animation until we reach the frame we should be
  // displaying now.
  // TODO(khushalsagar): Avoid unnecessary iterations for skipping whole loops
  // in the animations.
  size_t last_frame_index = frames_.size() - 1;
  size_t num_of_frames_advanced = 0u;
  while (next_desired_frame_time_ <= now && ShouldAnimate()) {
    num_of_frames_advanced++;
    size_t next_frame_index = NextFrameIndex();
    base::TimeTicks next_desired_frame_time =
        next_desired_frame_time_ + frames_[next_frame_index].duration;

    // The image may load more slowly than it's supposed to animate, so that by
    // the time we reach the end of the first repetition, we're well behind.
    // Start the animation from the first frame in this case, so that we don't
    // skip frames (or whole iterations) trying to "catch up".  This is a
    // tradeoff: It guarantees users see the whole animation the second time
    // through and don't miss any repetitions, and is closer to what other
    // browsers do; on the other hand, it makes animations "less accurate" for
    // pages that try to sync an image and some other resource (e.g. audio),
    // especially if users switch tabs (and thus stop drawing the animation,
    // which will pause it) during that initial loop, then switch back later.
    if (enable_image_animation_resync && next_frame_index == 0u &&
        repetitions_completed_ == 1 && next_desired_frame_time <= now) {
      pending_index_ = 0u;
      next_desired_frame_time_ = now + frames_[0].duration;
      repetitions_completed_ = 0;
      break;
    }

    pending_index_ = next_frame_index;
    next_desired_frame_time_ = next_desired_frame_time;

    // If we are advancing to the last frame and the image has been completely
    // loaded (which means that the frame count is known to be accurate), we
    // just finished a loop in the animation.
    if (pending_index_ == last_frame_index && is_complete())
      repetitions_completed_++;
  }

  // We should have advanced a single frame, anything more than that are frames
  // skipped trying to catch up.
  DCHECK_GT(num_of_frames_advanced, 0u);
  last_num_frames_skipped_ = num_of_frames_advanced - 1u;
  UMA_HISTOGRAM_COUNTS_100000("AnimatedImage.NumOfFramesSkipped.Compositor",
                              last_num_frames_skipped_);

  return pending_index_ != active_index_;
}

void ImageAnimationController::AnimationState::UpdateMetadata(
    const DiscardableImageMap::AnimatedImageMetadata& data) {
  paint_image_id_ = data.paint_image_id;

  DCHECK_NE(data.repetition_count, kAnimationNone);
  requested_repetitions_ = data.repetition_count;

  DCHECK(frames_.size() <= data.frames.size())
      << "Updated recordings can only append frames";
  frames_ = data.frames;
  DCHECK_GT(frames_.size(), 1u);

  DCHECK(completion_state_ != PaintImage::CompletionState::DONE ||
         data.completion_state == PaintImage::CompletionState::DONE)
      << "If the image was marked complete before, it can not be incomplete in "
         "a new update";
  completion_state_ = data.completion_state;

  // Update the repetition count in case we have displayed the last frame and
  // we now know the frame count to be accurate.
  size_t last_frame_index = frames_.size() - 1;
  if (pending_index_ == last_frame_index && is_complete() &&
      repetitions_completed_ == 0)
    repetitions_completed_++;

  // Reset the animation if the sequence id received in this recording was
  // incremented.
  if (reset_animation_sequence_id_ < data.reset_animation_sequence_id) {
    reset_animation_sequence_id_ = data.reset_animation_sequence_id;
    ResetAnimation();
  }
}

void ImageAnimationController::AnimationState::PushPendingToActive() {
  active_index_ = pending_index_;
}

void ImageAnimationController::AnimationState::AddDriver(
    AnimationDriver* driver) {
  drivers_.insert(driver);
}

void ImageAnimationController::AnimationState::RemoveDriver(
    AnimationDriver* driver) {
  drivers_.erase(driver);
}

void ImageAnimationController::AnimationState::UpdateStateFromDrivers() {
  should_animate_from_drivers_ = false;
  for (auto* driver : drivers_) {
    if (driver->ShouldAnimate(paint_image_id_)) {
      should_animate_from_drivers_ = true;
      break;
    }
  }
}

void ImageAnimationController::AnimationState::ResetAnimation() {
  animation_started_ = false;
  next_desired_frame_time_ = base::TimeTicks();
  repetitions_completed_ = 0;
  pending_index_ = 0u;
  // Don't reset the |active_index_|, tiles on the active tree still need it.
}

size_t ImageAnimationController::AnimationState::NextFrameIndex() const {
  if (!animation_started_)
    return 0u;
  return (pending_index_ + 1) % frames_.size();
}

ImageAnimationController::DelayedNotifier::DelayedNotifier(
    base::SingleThreadTaskRunner* task_runner,
    base::RepeatingClosure closure)
    : task_runner_(task_runner),
      closure_(std::move(closure)),
      weak_factory_(this) {
  DCHECK(task_runner_->BelongsToCurrentThread());
}

ImageAnimationController::DelayedNotifier::~DelayedNotifier() {
  DCHECK(task_runner_->BelongsToCurrentThread());
}

void ImageAnimationController::DelayedNotifier::Schedule(
    base::TimeTicks now,
    base::TimeTicks notification_time) {
  // If an animation is already pending, don't schedule another invalidation.
  // We will schedule the next invalidation based on the latest animation state
  // during AnimateForSyncTree.
  if (animation_pending_)
    return;

  // The requested notification time can be in the past. For instance, if an
  // animation was paused because the image became invisible.
  if (notification_time < now)
    notification_time = now;

  // If we already have a notification scheduled to run at this time, no need to
  // Cancel it.
  if (pending_notification_time_.has_value() &&
      notification_time == pending_notification_time_.value())
    return;

  // Cancel the pending notification since we the requested notification time
  // has changed.
  Cancel();

  TRACE_EVENT2("cc", "ScheduleInvalidationForImageAnimation",
               "notification_time", notification_time, "now", now);
  pending_notification_time_.emplace(notification_time);
  task_runner_->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&DelayedNotifier::Notify, weak_factory_.GetWeakPtr()),
      notification_time - now);
}

void ImageAnimationController::DelayedNotifier::Cancel() {
  pending_notification_time_.reset();
  weak_factory_.InvalidateWeakPtrs();
}

void ImageAnimationController::DelayedNotifier::Notify() {
  pending_notification_time_.reset();
  animation_pending_ = true;
  closure_.Run();
}

void ImageAnimationController::DelayedNotifier::WillAnimate() {
  animation_pending_ = false;
}

}  // namespace cc
