// Copyright 2015 Google Inc. 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/web_animations/baked_animation_set.h"

#include <algorithm>

#include "cobalt/web_animations/animation_effect_read_only.h"

namespace cobalt {
namespace web_animations {

// Extract Data objects from the Animation script objects.
BakedAnimation::BakedAnimation(const Animation& animation)
    : animation_data_(animation.data()),
      effect_timing_data_(animation.effect()->timing()->data()),
      keyframe_data_(base::polymorphic_downcast<const KeyframeEffectReadOnly*>(
                         animation.effect().get())
                         ->data()) {}

void BakedAnimation::Apply(const base::TimeDelta& timeline_time,
                           cssom::CSSComputedStyleData* in_out_style) const {
  // Get the animation's local time from the Animation::Data object.
  base::optional<base::TimeDelta> local_time =
      animation_data_.ComputeLocalTimeFromTimelineTime(timeline_time);

  // Obtain the iteration progress from the AnimationEffectTimingReadOnly::Data
  // object.
  AnimationEffectTimingReadOnly::Data::IterationProgress iteration_progress =
      effect_timing_data_.ComputeIterationProgressFromLocalTime(local_time);

  if (!iteration_progress.iteration_progress) {
    return;
  }

  // Use the iteration progress to animate the CSS style properties using
  // keyframe data stored in KeyframeEffectReadOnly::Data.
  keyframe_data_.ApplyAnimation(in_out_style,
                                *iteration_progress.iteration_progress,
                                *iteration_progress.current_iteration);
}

base::TimeDelta BakedAnimation::end_time() const {
  base::TimeDelta end_time_local =
      effect_timing_data_.time_until_after_phase(base::TimeDelta());

  return *animation_data_.ComputeTimelineTimeFromLocalTime(end_time_local);
}

BakedAnimationSet::BakedAnimationSet(const AnimationSet& animation_set) {
  for (AnimationSet::InternalSet::const_iterator iter =
           animation_set.animations().begin();
       iter != animation_set.animations().end(); ++iter) {
    animations_.push_back(new BakedAnimation(**iter));
  }
}

BakedAnimationSet::BakedAnimationSet(const BakedAnimationSet& rhs) {
  for (AnimationList::const_iterator iter = rhs.animations_.begin();
       iter != rhs.animations_.end(); ++iter) {
    animations_.push_back(new BakedAnimation(**iter));
  }
}

void BakedAnimationSet::Apply(const base::TimeDelta& timeline_time,
                              cssom::CSSComputedStyleData* in_out_style) const {
  // TODO: Follow the proceedure for combining effects.
  //   https://www.w3.org/TR/2015/WD-web-animations-1-20150707/#combining-effects
  for (AnimationList::const_iterator iter = animations_.begin();
       iter != animations_.end(); ++iter) {
    (*iter)->Apply(timeline_time, in_out_style);
  }
}

base::TimeDelta BakedAnimationSet::end_time() const {
  base::TimeDelta max_end_time = -base::TimeDelta::Max();
  for (AnimationList::const_iterator iter = animations_.begin();
       iter != animations_.end(); ++iter) {
    base::TimeDelta animation_end_time = (*iter)->end_time();
    max_end_time = std::max(animation_end_time, max_end_time);
  }
  return max_end_time;
}

}  // namespace web_animations
}  // namespace cobalt
