// 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/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
