// 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 <memory>
#include <utility>
#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, cssom::TransitionSet* transition_set) {
  // 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.
  std::unique_ptr<web_animations::Animation::EventHandler> event_handler =
      animation->AttachEventHandler(
          base::Bind(&CSSTransitionsAdapter::HandleAnimationEnterAfterPhase,
                     base::Unretained(this), transition_set));

  // 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, std::move(event_handler))));

  animation->Play();
}

void CSSTransitionsAdapter::OnTransitionRemoved(
    const cssom::Transition& transition,
    cssom::Transition::IsCanceled is_canceled) {
  // As described in the process for cancelling/stopping a transition here:
  //    https://dr.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.
  if (is_canceled == cssom::Transition::kIsNotCanceled) {
    // 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
    // Cobalt assumes that the CSSOM does not change during computed style
    // calculation. Post to dispatch the event asynchronously here to avoid
    // calling event handlers during computed style calculation, which in turn
    // may modify CSSOM and require restart of the computed style calculation.
    animatable_->GetEventTarget()->PostToDispatchEvent(
        FROM_HERE,
        new TransitionEvent(
            base::Tokens::transitionend(), transition.target_property(),
            static_cast<float>(transition.duration().InMillisecondsF())));
  }

  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(
    cssom::TransitionSet* transition_set) {
  DCHECK(animatable_->GetDefaultTimeline()->current_time());
  base::TimeDelta current_time = base::TimeDelta::FromMillisecondsD(
      animatable_->GetDefaultTimeline()->current_time().value_or(0));
  transition_set->UpdateTransitions(current_time,
                                    *animatable_->GetComputedStyle(),
                                    *animatable_->GetComputedStyle());
}

}  // namespace dom
}  // namespace cobalt
