// Copyright 2020 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/renderer/rasterizer/skia/skottie_animation.h"

#include "base/bind.h"

namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace skia {

SkottieAnimation::SkottieAnimation(const char* data, size_t length)
    : last_updated_animation_time_(base::TimeDelta()) {
  skottie::Animation::Builder builder;
  skottie_animation_ = builder.make(data, length);
  animation_size_ = math::Size(skottie_animation_->size().width(),
                               skottie_animation_->size().height());
  json_size_in_bytes_ = builder.getStats().fJsonSize;
}

void SkottieAnimation::SetProperties(LottieProperties properties) {
  properties_ = properties;
}

void SkottieAnimation::SetAnimationTime(base::TimeDelta animate_function_time) {
  // Seeking to a particular frame takes precedence over normal playback.
  // Check whether "seek()" has been called but has yet to occur.
  if (seek_counter_ != properties_.seek_counter) {
    base::TimeDelta current_animation_time;
    if (properties_.seek_value_is_frame) {
      skottie_animation_->seekFrame(properties_.seek_value);
      current_animation_time = base::TimeDelta::FromSecondsD(
          properties_.seek_value / skottie_animation_->fps());
    } else {
      skottie_animation_->seekFrameTime(properties_.seek_value *
                                        skottie_animation_->duration());
      current_animation_time = base::TimeDelta::FromSecondsD(
          properties_.seek_value * skottie_animation_->duration());
    }
    seek_counter_ = properties_.seek_counter;
    is_complete_ = false;
    UpdateAnimationFrameAndAnimateFunctionTimes(current_animation_time,
                                                animate_function_time);
    return;
  }

  // Reset the animation time to the start of the animation if the animation is
  // stopped.
  if (properties_.state == LottieState::kStopped) {
    skottie_animation_->seekFrameTime(0);
    is_complete_ = false;
    UpdateAnimationFrameAndAnimateFunctionTimes(base::TimeDelta(),
                                                animate_function_time);
    return;
  }

  // Do not update the animation time is the animation is paused.
  if (properties_.state == LottieState::kPaused) {
    skottie_animation_->seekFrameTime(
        last_updated_animation_time_.InSecondsF());
    UpdateAnimationFrameAndAnimateFunctionTimes(last_updated_animation_time_,
                                                animate_function_time);
    return;
  }

  DCHECK(properties_.state == LottieState::kPlaying);
  base::TimeDelta current_animation_time = last_updated_animation_time_;
  base::TimeDelta time_elapsed =
      animate_function_time - last_updated_animate_function_time_;
  current_animation_time += time_elapsed * properties_.speed;
  base::TimeDelta animation_duration =
      base::TimeDelta::FromSecondsD(skottie_animation_->duration());

  if (properties_.loop) {
    // If the animation mode is "bounce", then the animation should change
    // the direction in which it plays after each loop.
    int new_loop_count = floor(current_animation_time / animation_duration);

    // Check whether the number of loops exceeds the limits set by
    // LottieProperties::count.
    // (Note: LottieProperties::count refers to the number of loops after the
    // animation plays once through.)
    if (properties_.count > 0 && new_loop_count > properties_.count) {
      current_animation_time = animation_duration;
    } else {
      // If the animation should continue playing, check whether the animation
      // has completed and needs to trigger a "loop" and potentially reverse
      // direction.
      if (new_loop_count > total_loops_) {
        if (!properties_.onloop_callback.is_null()) {
          properties_.onloop_callback.Run();
        }
        if (properties_.mode == LottieMode::kBounce) {
          direction_ *= -1;
        }
      }
      current_animation_time = base::TimeDelta::FromSecondsD(
          std::fmod(current_animation_time.InSecondsF(),
                    animation_duration.InSecondsF()));
    }
    total_loops_ = new_loop_count;
  }

  if (direction_ * properties_.direction == -1) {
    current_animation_time = animation_duration - current_animation_time;
  }

  if (!is_complete_ && current_animation_time > animation_duration &&
      !properties_.oncomplete_callback.is_null()) {
    is_complete_ = true;
    properties_.oncomplete_callback.Run();
  }

  skottie_animation_->seekFrameTime(current_animation_time.InSecondsF());
  UpdateAnimationFrameAndAnimateFunctionTimes(current_animation_time,
                                              animate_function_time);
}

void SkottieAnimation::UpdateAnimationFrameAndAnimateFunctionTimes(
    base::TimeDelta current_animation_time,
    base::TimeDelta current_animate_function_time) {
  if (current_animation_time == last_updated_animation_time_) {
    return;
  }

  // Dispatch a frame event every time a new frame is entered, and if the
  // animation is not complete.
  double frame =
      current_animation_time.InSecondsF() * skottie_animation_->fps();
  double seeker = current_animation_time.InSecondsF() /
                  skottie_animation_->duration() * 100;
  if (!properties_.onenterframe_callback.is_null() && !is_complete_) {
    properties_.onenterframe_callback.Run(frame, seeker);
  }

  last_updated_animation_time_ = current_animation_time;
  last_updated_animate_function_time_ = current_animate_function_time;
}

}  // namespace skia
}  // namespace rasterizer
}  // namespace renderer
}  // namespace cobalt
