// Copyright 2015 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/dom/css_transitions_adapter.h"

#include <vector>

#include "cobalt/base/tokens.h"
#include "cobalt/dom/document.h"
#include "cobalt/dom/dom_animatable.h"
#include "cobalt/dom/element.h"
#include "cobalt/dom/html_element.h"
#include "cobalt/dom/pseudo_element.h"
#include "cobalt/dom/transition_event.h"
#include "cobalt/web_animations/keyframe.h"
#include "cobalt/web_animations/keyframe_effect_read_only.h"

namespace cobalt {
namespace dom {

CSSTransitionsAdapter::CSSTransitionsAdapter(
    const scoped_refptr<dom::DOMAnimatable>& target)
    : animatable_(target) {}

CSSTransitionsAdapter::~CSSTransitionsAdapter() {
  for (PropertyValueAnimationMap::iterator iter = animation_map_.begin();
       iter != animation_map_.end(); ++iter) {
    delete iter->second;
  }
}

void CSSTransitionsAdapter::OnTransitionStarted(
    const cssom::Transition& transition) {
  // The process for constructing web animations from CSS transitions is
  // described here:
  //   https://drafts.csswg.org/date/2015-03-02/web-animations-css-integration/#css-transitions

  // Create our timing structure using the timing information from the
  // transition.
  scoped_refptr<web_animations::AnimationEffectTimingReadOnly> timing_input(
      new web_animations::AnimationEffectTimingReadOnly(
          transition.delay(), base::TimeDelta(),
          web_animations::AnimationEffectTimingReadOnly::kBoth, 0.0, 1.0,
          transition.duration(),
          web_animations::AnimationEffectTimingReadOnly::kNormal,
          cssom::TimingFunction::GetLinear()));

  // Setup a KeyframeEffect with 2 keyframes, a start and end frame that hold
  // the start and end transition property values.  In general keyframes can
  // contain values for many properties, but for transitions they will only
  // ever have the transition's target property.
  std::vector<web_animations::Keyframe::Data> frames;

  web_animations::Keyframe::Data start_frame(0.0);
  start_frame.set_easing(transition.timing_function());
  start_frame.AddPropertyValue(transition.target_property(),
                               transition.start_value());
  frames.push_back(start_frame);

  web_animations::Keyframe::Data end_frame(1.0);
  end_frame.AddPropertyValue(transition.target_property(),
                             transition.end_value());
  frames.push_back(end_frame);

  scoped_refptr<web_animations::KeyframeEffectReadOnly> keyframe_effect(
      new web_animations::KeyframeEffectReadOnly(timing_input, animatable_,
                                                 frames));

  // Finally setup and play our animation.
  scoped_refptr<web_animations::Animation> animation(
      new web_animations::Animation(keyframe_effect,
                                    animatable_->GetDefaultTimeline()));

  // Setup an event handler on the animation so we can watch for when it enters
  // the after phase, allowing us to then trigger the transitionend event.
  scoped_ptr<web_animations::Animation::EventHandler> event_handler =
      animation->AttachEventHandler(
          base::Bind(&CSSTransitionsAdapter::HandleAnimationEnterAfterPhase,
                     base::Unretained(this), transition));

  // Track the animation in our map of all CSS Transitions-created animations.
  DCHECK(animation_map_.find(transition.target_property()) ==
         animation_map_.end());

  animation_map_.insert(std::make_pair(
      transition.target_property(),
      new AnimationWithEventHandler(animation, event_handler.Pass())));

  animation->Play();
}

void CSSTransitionsAdapter::OnTransitionRemoved(
    const cssom::Transition& transition) {
  // As described in the process for cancelling/stopping a transition here:
  //    https://drafts.csswg.org/date/2015-03-02/web-animations-css-integration/Overview.html#css-transitions
  // We find the animation corresponding to the removed transition, cancel it,
  // and then remove it from our record of animations.
  PropertyValueAnimationMap::iterator found =
      animation_map_.find(transition.target_property());
  DCHECK(animation_map_.end() != found);

  found->second->animation->Cancel();
  delete found->second;
  animation_map_.erase(found);
}

void CSSTransitionsAdapter::HandleAnimationEnterAfterPhase(
    const cssom::Transition& transition) {
  // An animation corresponding to a transition has entered the "after phase",
  // so we should correspondingly fire the transitionend event.
  //   https://drafts.csswg.org/date/2015-03-02/web-animations-css-integration/#css-transitions-events
  animatable_->GetEventTarget()->DispatchEvent(new TransitionEvent(
      base::Tokens::transitionend(), transition.target_property(),
      static_cast<float>(transition.duration().InMillisecondsF())));
}

}  // namespace dom
}  // namespace cobalt
