/*
 * 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 "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.InMillisecondsF());

  // 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);
}

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);
  }
}

}  // namespace web_animations
}  // namespace cobalt
