// 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/web_animations/keyframe_effect_read_only.h"

#include <utility>

#include "base/logging.h"
#include "base/optional.h"
#include "cobalt/cssom/interpolate_property_value.h"
#include "cobalt/cssom/property_definitions.h"

namespace cobalt {
namespace web_animations {

KeyframeEffectReadOnly::KeyframeEffectReadOnly(
    const scoped_refptr<AnimationEffectTimingReadOnly>& timing,
    const scoped_refptr<Animatable>& target,
    const std::vector<scoped_refptr<Keyframe> >& frames)
    : AnimationEffectReadOnly(timing), target_(target), data_(frames) {}

KeyframeEffectReadOnly::KeyframeEffectReadOnly(
    const scoped_refptr<AnimationEffectTimingReadOnly>& timing,
    const scoped_refptr<Animatable>& target,
    const Data::KeyframeSequence& frames)
    : AnimationEffectReadOnly(timing), target_(target), data_(frames) {}

KeyframeEffectReadOnly::Data::Data(const KeyframeSequence& keyframes)
    : keyframes_(keyframes) {
  CheckKeyframesSorted();
  PopulatePropertiesAffected();
}

KeyframeEffectReadOnly::Data::Data(
    const std::vector<scoped_refptr<Keyframe> >& keyframes) {
  // For each Keyframe object, we must extract and store its associated
  // Keyframe::Data object into a separate but parallel vector that we
  // internally store as our list of keyframes.
  for (std::vector<scoped_refptr<Keyframe> >::const_iterator iter =
           keyframes.begin();
       iter != keyframes.end(); ++iter) {
    keyframes_.push_back((*iter)->data());
  }
  CheckKeyframesSorted();
  PopulatePropertiesAffected();
}

void KeyframeEffectReadOnly::Data::CheckKeyframesSorted() const {
  base::Optional<double> last_offset;
  for (KeyframeSequence::const_iterator iter = keyframes_.begin();
       iter != keyframes_.end(); ++iter) {
    DCHECK(iter->offset())
        << "We currently do not support automatic spacing of keyframes.";
    if (last_offset) {
      DCHECK_GE(*iter->offset(), *last_offset);
    }
    last_offset = iter->offset();
  }
}

void KeyframeEffectReadOnly::Data::PopulatePropertiesAffected() {
  // Compute a set of all properties affected by this effect by iterating
  // through our list of keyframes and querying them for the properties that
  // they affect.
  for (KeyframeSequence::const_iterator iter = keyframes_.begin();
       iter != keyframes_.end(); ++iter) {
    const Keyframe::Data& keyframe = *iter;
    for (Keyframe::Data::PropertyValueMap::const_iterator prop_iter =
             keyframe.property_values().begin();
         prop_iter != keyframe.property_values().end(); ++prop_iter) {
      properties_affected_.insert(prop_iter->first);
    }
  }
}

bool KeyframeEffectReadOnly::Data::IsPropertyAnimated(
    cssom::PropertyKey property) const {
  return properties_affected_.find(property) != properties_affected_.end();
}

bool KeyframeEffectReadOnly::Data::IsOnlyPropertyAnimated(
    cssom::PropertyKey property) const {
  if (properties_affected_.size() != 1) {
    return false;
  }

  return *properties_affected_.begin() == property;
}

void KeyframeEffectReadOnly::Data::ApplyAnimation(
    const scoped_refptr<cssom::MutableCSSComputedStyleData>& in_out_style,
    double iteration_progress, double current_iteration) const {
  for (std::set<cssom::PropertyKey>::const_iterator iter =
           properties_affected_.begin();
       iter != properties_affected_.end(); ++iter) {
    if (GetPropertyAnimatable(*iter)) {
      in_out_style->SetPropertyValue(
          *iter, ComputeAnimatedPropertyValue(
                     *iter, in_out_style->GetPropertyValue(*iter),
                     iteration_progress, current_iteration));
    } else {
      NOTIMPLEMENTED() << GetPropertyName(*iter) << " is not animatable.";
    }
  }
}

namespace {
struct PropertySpecificKeyframe {
  static PropertySpecificKeyframe DefaultBeginFrame(
      const scoped_refptr<cssom::PropertyValue>& underlying_value) {
    return PropertySpecificKeyframe(0.0, cssom::TimingFunction::GetLinear(),
                                    underlying_value);
  }
  static PropertySpecificKeyframe DefaultEndFrame(
      const scoped_refptr<cssom::PropertyValue>& underlying_value) {
    return PropertySpecificKeyframe(1.0, cssom::TimingFunction::GetLinear(),
                                    underlying_value);
  }
  static PropertySpecificKeyframe FromKeyframe(
      const Keyframe::Data& keyframe, cssom::PropertyKey target_property) {
    Keyframe::Data::PropertyValueMap::const_iterator found =
        keyframe.property_values().find(target_property);
    DCHECK(found != keyframe.property_values().end());

    return PropertySpecificKeyframe(*keyframe.offset(), keyframe.easing(),
                                    found->second);
  }

  PropertySpecificKeyframe(double offset,
                           const scoped_refptr<cssom::TimingFunction>& easing,
                           const scoped_refptr<cssom::PropertyValue>& value)
      : offset(offset), easing(easing), value(value) {}

  double offset;
  scoped_refptr<cssom::TimingFunction> easing;
  scoped_refptr<cssom::PropertyValue> value;
};

int NumberOfKeyframesWithOffsetOfZero(
    const KeyframeEffectReadOnly::Data::KeyframeSequence& keyframes,
    cssom::PropertyKey target_property) {
  int number_of_keyframes_with_offset_of_zero = 0;

  // Since the keyframes are sorted we simply iterate through them in sequence
  // until we find one with an offset greater than zero.
  for (KeyframeEffectReadOnly::Data::KeyframeSequence::const_iterator iter =
           keyframes.begin();
       iter != keyframes.end(); ++iter) {
    if (iter->AffectsProperty(target_property)) {
      DCHECK(iter->offset());
      if (*iter->offset() == 0.0) {
        ++number_of_keyframes_with_offset_of_zero;
      } else {
        break;
      }
    }
  }

  return number_of_keyframes_with_offset_of_zero;
}

int NumberOfKeyframesWithOffsetOfOne(
    const KeyframeEffectReadOnly::Data::KeyframeSequence& keyframes,
    cssom::PropertyKey target_property) {
  int number_of_keyframes_with_offset_of_one = 0;

  // Since the keyframes are sorted we simply iterate through them in reverse
  // order until we find one with an offset less than one.
  for (KeyframeEffectReadOnly::Data::KeyframeSequence::const_reverse_iterator
           iter = keyframes.rbegin();
       iter != keyframes.rend(); ++iter) {
    if (iter->AffectsProperty(target_property)) {
      DCHECK(iter->offset());
      if (*iter->offset() == 1.0) {
        ++number_of_keyframes_with_offset_of_one;
      } else {
        break;
      }
    }
  }

  return number_of_keyframes_with_offset_of_one;
}

template <typename T>
T FirstWithProperty(const T& start, const T& end,
                    cssom::PropertyKey target_property) {
  T iter = start;
  for (; iter != end; ++iter) {
    if (iter->AffectsProperty(target_property)) {
      return iter;
    }
  }
  return iter;
}

}  // namespace

// Described within step 10 from:
//   https://www.w3.org/TR/2015/WD-web-animations-1-20150707/#the-effect-value-of-a-keyframe-animation-effect
std::pair<base::Optional<PropertySpecificKeyframe>,
          base::Optional<PropertySpecificKeyframe> >
ComputeIntervalEndpoints(
    const KeyframeEffectReadOnly::Data::KeyframeSequence& keyframes,
    cssom::PropertyKey target_property,
    const scoped_refptr<cssom::PropertyValue>& underlying_value,
    double iteration_progress) {
  // We create a default being/end frame only if we find that we need them.
  std::pair<base::Optional<PropertySpecificKeyframe>,
            base::Optional<PropertySpecificKeyframe> >
      interval_endpoints;

  if (iteration_progress < 0.0 &&
      NumberOfKeyframesWithOffsetOfZero(keyframes, target_property) > 1) {
    interval_endpoints.first = PropertySpecificKeyframe::FromKeyframe(
        *FirstWithProperty(keyframes.begin(), keyframes.end(), target_property),
        target_property);
  } else if (iteration_progress >= 1.0 &&
             NumberOfKeyframesWithOffsetOfOne(keyframes, target_property) > 1) {
    interval_endpoints.first = PropertySpecificKeyframe::FromKeyframe(
        *FirstWithProperty(keyframes.rbegin(), keyframes.rend(),
                           target_property),
        target_property);
  } else {
    // Find the keyframe immediately preceding the iteration_progress and set
    // that to the first endpoint, and set the next keyframe as the second
    // endpoint.
    KeyframeEffectReadOnly::Data::KeyframeSequence::const_iterator prev_iter =
        keyframes.end();
    KeyframeEffectReadOnly::Data::KeyframeSequence::const_iterator iter =
        keyframes.begin();
    for (; iter != keyframes.end(); ++iter) {
      if (iter->AffectsProperty(target_property)) {
        if (*iter->offset() > iteration_progress || *iter->offset() == 1.0) {
          break;
        }
        prev_iter = iter;
      }
    }

    if (prev_iter == keyframes.end() && *iter->offset() == 0.0) {
      DCHECK_LT(iteration_progress, 0.0);
      // In the case that iteration progress is negative, the first keyframe
      // should be set to the last (the only one, if it exists) keyframe with
      // an offset of 0.
      prev_iter = iter;
      iter = FirstWithProperty(iter + 1, keyframes.end(), target_property);
    }

    interval_endpoints.first =
        prev_iter == keyframes.end()
            ? PropertySpecificKeyframe::DefaultBeginFrame(underlying_value)
            : PropertySpecificKeyframe::FromKeyframe(*prev_iter,
                                                     target_property);
    interval_endpoints.second =
        iter == keyframes.end()
            ? PropertySpecificKeyframe::DefaultEndFrame(underlying_value)
            : PropertySpecificKeyframe::FromKeyframe(*iter, target_property);
  }

  return interval_endpoints;
}

// https://www.w3.org/TR/2015/WD-web-animations-1-20150707/#the-effect-value-of-a-keyframe-animation-effect
scoped_refptr<cssom::PropertyValue>
KeyframeEffectReadOnly::Data::ComputeAnimatedPropertyValue(
    cssom::PropertyKey target_property,
    const scoped_refptr<cssom::PropertyValue>& underlying_value,
    double iteration_progress, double current_iteration) const {
  // Since not all steps are implemented here, this parameter is not yet
  // referenced in our implementation.

  // 6. If property-specific keyframes is empty, return underlying value.
  if (!IsPropertyAnimated(target_property)) {
    return underlying_value;
  }

  // 10. (see URL above for description).
  std::pair<base::Optional<PropertySpecificKeyframe>,
            base::Optional<PropertySpecificKeyframe> >
      interval_endpoints = ComputeIntervalEndpoints(
          keyframes_, target_property, underlying_value, iteration_progress);

  // 12. If there is only one keyframe in interval endpoints return the property
  //     value of target property on that keyframe.
  if (!interval_endpoints.second) {
    return interval_endpoints.first->value;
  }

  // 13. Let start offset be the computed keyframe offset of the first keyframe
  //     in interval endpoints.
  double start_offset = interval_endpoints.first->offset;

  // 14. Let end offset be the computed keyframe offset of last keyframe in
  //     interval endpoints.
  double end_offset = interval_endpoints.second->offset;

  // 15. Let interval distance be the result of evaluating
  //     (iteration progress - start offset) / (end offset - start offset)
  double interval_distance =
      (iteration_progress - start_offset) / (end_offset - start_offset);

  // NOT IN SPEC. This seems missing from the specification, but this is the
  //              place where per-keyframe timing functions should be applied.
  float scaled_interval_distance =
      interval_endpoints.first->easing != cssom::TimingFunction::GetLinear()
          ? interval_endpoints.first->easing->Evaluate(
                static_cast<float>(interval_distance))
          : static_cast<float>(interval_distance);

  // 16. Return the result of applying the interpolation procedure defined by
  //     the animation behavior of the target property, to the values of the
  //     target property specified on the two keyframes in interval endpoints
  //     taking the first such value as V_start and the second as V_end and
  //     using interval distance as the interpolation parameter p.
  return InterpolatePropertyValue(scaled_interval_distance,
                                  interval_endpoints.first->value,
                                  interval_endpoints.second->value);
}

void KeyframeEffectReadOnly::TraceMembers(script::Tracer* tracer) {
  AnimationEffectReadOnly::TraceMembers(tracer);

  tracer->Trace(target_.get());
}

}  // namespace web_animations
}  // namespace cobalt
