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

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

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
