/*
 * 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/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::CSSComputedStyleData>& 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.
  UNREFERENCED_PARAMETER(current_iteration);

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

}  // namespace web_animations
}  // namespace cobalt
