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