// 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/cssom/css_transition_set.h"

#include <algorithm>
#include <cmath>

#include "base/lazy_instance.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/cssom/css_computed_style_data.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/cssom/property_key_list_value.h"
#include "cobalt/cssom/property_value.h"
#include "cobalt/cssom/time_list_value.h"
#include "cobalt/cssom/timing_function_list_value.h"

namespace cobalt {
namespace cssom {

namespace {
// Returns the index at which the property should be animated.  If the property
// should not be animated, -1 is returned.
int GetPropertyTransitionIndex(
    PropertyKey property,
    const scoped_refptr<const PropertyValue>& transition_property_value) {
  if (transition_property_value == KeywordValue::GetNone()) {
    return -1;
  } else {
    const PropertyKeyListValue* property_name_list =
        base::polymorphic_downcast<const PropertyKeyListValue*>(
            transition_property_value.get());

    // The LAST reference to the given property in the transition-property list
    // is the one we use to determine the property's index, so start searching
    // for it from the back to the front.
    //   https://www.w3.org/TR/2013/WD-css3-transitions-20131119/#transition-property-property
    for (int i = static_cast<int>(property_name_list->value().size()) - 1;
         i >= 0; --i) {
      PropertyKey current_list_property =
          property_name_list->value()[static_cast<size_t>(i)];
      if (current_list_property == kAllProperty ||
          current_list_property == property) {
        return i;
      }
    }
  }

  return -1;
}
}  // namespace

TransitionSet::TransitionSet(EventHandler* event_handler)
    : transitions_(event_handler) {}

void TransitionSet::UpdateTransitions(
    const base::TimeDelta& current_time,
    const CSSComputedStyleData& source_computed_style,
    const CSSComputedStyleData& destination_computed_style) {
  const TimeListValue* transition_duration =
      base::polymorphic_downcast<const TimeListValue*>(
          destination_computed_style.transition_duration().get());
  if (transition_duration->value().size() == 1 &&
      transition_duration->value()[0] == base::TimeDelta() &&
      transitions_.IsEmpty()) {
    // No need to process transitions if all their durations are set to
    // 0, the initial value, so this will happen often.
    return;
  }

  // For each animatable property, check to see if there are any transitions
  // assigned to it.  If so, check to see if there are any existing transitions
  // that must be updated, otherwise introduce new transitions.
  const PropertyKeyVector& animatable_properties = GetAnimatableProperties();
  for (PropertyKeyVector::const_iterator iter = animatable_properties.begin();
       iter != animatable_properties.end(); ++iter) {
    UpdateTransitionForProperty(
        *iter, current_time, source_computed_style.GetPropertyValue(*iter),
        destination_computed_style.GetPropertyValue(*iter),
        destination_computed_style);
  }
}

namespace {
void SetReversingValues(
    const base::TimeDelta& current_time, const Transition& old_transition,
    const scoped_refptr<PropertyValue>& new_start_value,
    const scoped_refptr<PropertyValue>& new_end_value,
    scoped_refptr<PropertyValue>* new_reversing_adjusted_start_value,
    float* new_reversing_shortening_factor) {
  // This value is calculated as explained here:
  //   https://www.w3.org/TR/css3-transitions/#reversing
  // These calculations make a pleasant experience when reversing a transition
  // half-way through by making the reverse transition occur over half as much
  // time.
  if (old_transition.reversing_adjusted_start_value()->Equals(*new_end_value)) {
    *new_reversing_shortening_factor =
        std::min<float>(1.0f, std::max<float>(0.0f,
            std::abs(old_transition.Progress(current_time) *
                         old_transition.reversing_shortening_factor() +
                     1 - old_transition.reversing_shortening_factor())));

    *new_reversing_adjusted_start_value = old_transition.end_value();
  } else {
    *new_reversing_adjusted_start_value = new_start_value;
    *new_reversing_shortening_factor = 1.0f;
  }
}

base::TimeDelta ScaleTimeDelta(const base::TimeDelta& time_delta, float scale) {
  return base::TimeDelta::FromMicroseconds(static_cast<int64>(
      time_delta.InSecondsF() * scale * base::Time::kMicrosecondsPerSecond));
}

// Given that a new transition has started on a CSS value that had an active old
// transition occurring on it, this function creates a new transition based on
// the old transition's values (so that we can smoothly transition out of the
// middle of an old transition).
Transition CreateTransitionOverOldTransition(
    PropertyKey property, const base::TimeDelta& current_time,
    const Transition& old_transition, const base::TimeDelta& duration,
    const base::TimeDelta& delay,
    const scoped_refptr<TimingFunction>& timing_function,
    const scoped_refptr<PropertyValue>& end_value) {
  // Since we're updating an old transtion, we'll need to know the animated
  // CSS style value from the old transition at this point in time.
  scoped_refptr<PropertyValue> current_value_within_old_transition =
      old_transition.Evaluate(current_time);

  // If the new transition is a reversal fo the old transition, we need to
  // setup reversing_adjusted_start_value and reversing_shortening_factor so
  // that they can be used to reduce the new transition's duration.
  scoped_refptr<PropertyValue> new_reversing_adjusted_start_value;
  float new_reversing_shortening_factor;
  SetReversingValues(current_time, old_transition,
                     current_value_within_old_transition, end_value,
                     &new_reversing_adjusted_start_value,
                     &new_reversing_shortening_factor);

  base::TimeDelta with_reversing_delay =
      delay < base::TimeDelta()
          ? ScaleTimeDelta(delay, new_reversing_shortening_factor)
          : delay;

  return Transition(
      property, current_value_within_old_transition, end_value, current_time,
      ScaleTimeDelta(duration, new_reversing_shortening_factor),
      with_reversing_delay, timing_function, new_reversing_adjusted_start_value,
      new_reversing_shortening_factor);
}

}  // namespace

void TransitionSet::UpdateTransitionForProperty(
    PropertyKey property, const base::TimeDelta& current_time,
    const scoped_refptr<PropertyValue>& start_value,
    const scoped_refptr<PropertyValue>& end_value,
    const CSSComputedStyleData& transition_style) {
  // This method essentially implements the logic defined at
  //   https://www.w3.org/TR/css3-transitions/#starting

  // Get the index of this property in the transition-property list, so we
  // can know if the property should be animated (i.e. it is animated if it
  // is in the list) and also how to match up transition-duration and other
  // transition attributes to it.
  int transition_index = GetPropertyTransitionIndex(
      property, transition_style.transition_property());

  // The property is only animated if its transition duration is greater than 0.
  const TimeListValue* transition_duration =
      base::polymorphic_downcast<const TimeListValue*>(
          transition_style.transition_duration().get());

  // Get animation parameters by using the transition_index modulo the
  // specific property sizes.  This is inline with the specification which
  // states that list property values should be repeated to calculate values
  // for indices larger than the list's size.
  base::TimeDelta duration =
      transition_index < 0
          ? base::TimeDelta()
          : transition_duration->get_item_modulo_size(transition_index);

  if (!duration.is_zero()) {
    if (duration.InMilliseconds() != 0 && !start_value->Equals(*end_value)) {
      TimeListValue* delay_list = base::polymorphic_downcast<TimeListValue*>(
          transition_style.transition_delay().get());
      const base::TimeDelta& delay =
          delay_list->get_item_modulo_size(transition_index);

      TimingFunctionListValue* timing_function_list =
          base::polymorphic_downcast<TimingFunctionListValue*>(
              transition_style.transition_timing_function().get());
      const scoped_refptr<TimingFunction>& timing_function =
          timing_function_list->get_item_modulo_size(transition_index);

      // The property has been modified and the transition should be animated.
      // We now check if an active transition for this property already exists
      // or not.
      const Transition* existing_transition =
          transitions_.GetTransitionForProperty(property);

      if (existing_transition &&
          current_time < existing_transition->EndTime()) {
        // A transition is already occurring, so we handle this case a bit
        // differently depending on if we're reversing the previous transition
        // or starting a completely different one.
        transitions_.UpdateTransitionForProperty(
            property, CreateTransitionOverOldTransition(
                          property, current_time, *existing_transition,
                          duration, delay, timing_function, end_value));
      } else {
        // There is no transition on the object currently, so create a new
        // one for it.
        transitions_.UpdateTransitionForProperty(
            property,
            Transition(property, start_value, end_value, current_time, duration,
                       delay, timing_function, start_value, 1.0f));
      }
    } else {
      // Check if there is an existing transition for this property and see
      // if it has completed yet.  If so, remove it from the list of
      // transformations.
      // TODO: Fire off a transitionend event.
      //   https://www.w3.org/TR/css3-transitions/#transitionend
      const Transition* transition =
          transitions_.GetTransitionForProperty(property);
      if (transition != NULL) {
        if (current_time >= transition->EndTime()) {
          transitions_.RemoveTransitionForProperty(property);
        }
      }
    }
  } else {
    // The property is not in the transition-property list, thus it should no
    // longer be animated.  Remove the transition if it exists.  It does
    // not generate a transitionend event, it does not pass go, it does not
    // collect $200.
    if (transitions_.GetTransitionForProperty(property)) {
      transitions_.RemoveTransitionForProperty(property);
    }
  }
}

const Transition* TransitionSet::GetTransitionForProperty(
    PropertyKey property) const {
  return transitions_.GetTransitionForProperty(property);
}

void TransitionSet::Clear() { transitions_.Clear(); }

TransitionSet::TransitionMap::TransitionMap(EventHandler* event_handler)
    : event_handler_(event_handler) {}

TransitionSet::TransitionMap::~TransitionMap() {
  if (event_handler_ != NULL) {
    for (InternalTransitionMap::iterator iter = transitions_.begin();
         iter != transitions_.end(); ++iter) {
      event_handler_->OnTransitionRemoved(iter->second);
    }
  }
}

const Transition* TransitionSet::TransitionMap::GetTransitionForProperty(
    PropertyKey property) const {
  InternalTransitionMap::const_iterator found = transitions_.find(property);
  if (found == transitions_.end()) return NULL;

  return &found->second;
}

void TransitionSet::TransitionMap::UpdateTransitionForProperty(
    PropertyKey property, const Transition& transition) {
  InternalTransitionMap::iterator found = transitions_.find(property);
  if (found != transitions_.end()) {
    if (event_handler_ != NULL) {
      event_handler_->OnTransitionRemoved(found->second);
    }
    found->second = transition;
  } else {
    transitions_.insert(std::make_pair(property, transition));
  }

  if (event_handler_ != NULL) {
    event_handler_->OnTransitionStarted(transition);
  }
}

void TransitionSet::TransitionMap::RemoveTransitionForProperty(
    PropertyKey property) {
  InternalTransitionMap::iterator found = transitions_.find(property);
  DCHECK(found != transitions_.end());

  if (event_handler_ != NULL) {
    event_handler_->OnTransitionRemoved(found->second);
  }

  transitions_.erase(found);
}

void TransitionSet::TransitionMap::Clear() {
  if (event_handler_ != NULL) {
    for (auto& transition : transitions_) {
      event_handler_->OnTransitionRemoved(transition.second);
    }
  }

  transitions_.clear();
}

namespace {
base::LazyInstance<TransitionSet> g_empty_transition_set =
    LAZY_INSTANCE_INITIALIZER;
}  // namespace

const TransitionSet* TransitionSet::EmptyTransitionSet() {
  return &g_empty_transition_set.Get();
}

}  // namespace cssom
}  // namespace cobalt
