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

#include <limits>
#include <map>
#include <set>
#include <string>
#include <vector>

#include "cobalt/cssom/keyword_value.h"
#include "cobalt/cssom/number_value.h"
#include "cobalt/cssom/property_list_value.h"
#include "cobalt/cssom/string_value.h"
#include "cobalt/cssom/time_list_value.h"
#include "cobalt/cssom/timing_function_list_value.h"

namespace cobalt {
namespace cssom {

AnimationSet::AnimationSet(EventHandler* event_handler)
    : event_handler_(event_handler) {}

namespace {
base::TimeDelta GetTimeValue(size_t index, PropertyValue* list_value) {
  return base::polymorphic_downcast<TimeListValue*>(list_value)
      ->get_item_modulo_size(static_cast<int>(index));
}

Animation::FillMode GetFillMode(size_t index, PropertyValue* list_value) {
  PropertyValue* value =
      base::polymorphic_downcast<PropertyListValue*>(list_value)
          ->get_item_modulo_size(static_cast<int>(index));

  if (value == KeywordValue::GetNone()) {
    return Animation::kNone;
  } else if (value == KeywordValue::GetForwards()) {
    return Animation::kForwards;
  } else if (value == KeywordValue::GetBackwards()) {
    return Animation::kBackwards;
  } else if (value == KeywordValue::GetBoth()) {
    return Animation::kBoth;
  } else {
    NOTREACHED();
    return Animation::kNone;
  }
}

Animation::PlaybackDirection GetDirection(size_t index,
                                          PropertyValue* list_value) {
  PropertyValue* value =
      base::polymorphic_downcast<PropertyListValue*>(list_value)
          ->get_item_modulo_size(static_cast<int>(index));

  if (value == KeywordValue::GetNormal()) {
    return Animation::kNormal;
  } else if (value == KeywordValue::GetReverse()) {
    return Animation::kReverse;
  } else if (value == KeywordValue::GetAlternate()) {
    return Animation::kAlternate;
  } else if (value == KeywordValue::GetAlternateReverse()) {
    return Animation::kAlternateReverse;
  } else {
    NOTREACHED();
    return Animation::kNormal;
  }
}

float GetIterationCount(size_t index, PropertyValue* list_value) {
  PropertyValue* value =
      base::polymorphic_downcast<PropertyListValue*>(list_value)
          ->get_item_modulo_size(static_cast<int>(index));

  if (value == KeywordValue::GetInfinite()) {
    return std::numeric_limits<float>::infinity();
  } else {
    return base::polymorphic_downcast<NumberValue*>(value)->value();
  }
}

scoped_refptr<TimingFunction> GetTimingFunction(size_t index,
                                                PropertyValue* list_value) {
  return base::polymorphic_downcast<TimingFunctionListValue*>(list_value)
      ->get_item_modulo_size(static_cast<int>(index));
}
}  // namespace

bool AnimationSet::Update(const base::TimeDelta& current_time,
                          const CSSComputedStyleData& style,
                          const CSSKeyframesRule::NameMap& keyframes_map) {
  const std::vector<scoped_refptr<PropertyValue> >& names =
      base::polymorphic_downcast<PropertyListValue*>(
          style.animation_name().get())
          ->value();

  // There should always be at least one element in the list (e.g. the
  // 'none' keyword).
  DCHECK_LE(static_cast<size_t>(1), names.size());

  if (animations_.empty() && names.size() == 1 &&
      names[0] == KeywordValue::GetNone()) {
    // If we have no current animations playing and no animations were
    // specified, there is nothing to do so we can return immediately.
    return false;
  }

  // Whether or not the animations have been modified by this update.
  bool animations_modified = false;

  // Build a set of all animations in the new declared animation set, so that
  // we can later use this to decide which old animations are no longer active.
  std::set<std::string> declared_animation_set;

  for (size_t i = 0; i < names.size(); ++i) {
    // If 'none' is specified as the animation name, this animation list element
    // is a no-op, skip it.
    if (names[i] == KeywordValue::GetNone()) {
      continue;
    }

    // Take note of the appearance of this string in 'animation-name' so that
    // we can check later which 'animation-names' used to be in the list but
    // no longer are.
    const std::string& name_string =
        base::polymorphic_downcast<StringValue*>(names[i].get())->value();
    declared_animation_set.insert(name_string);

    if (animations_.find(name_string) != animations_.end()) {
      // If the animation is already playing, we shouldn't interfere with it.
      continue;
    }

    // A new animation not previously started is being introduced, start by
    // looking up its keyframes rule (which may not exist).
    scoped_refptr<CSSKeyframesRule> keyframes;
    CSSKeyframesRule::NameMap::const_iterator found =
        keyframes_map.find(name_string);
    if (found != keyframes_map.end()) {
      keyframes = found->second;
    } else {
      LOG(WARNING) << "animation-name referenced undefined @keyframes rule, '"
                   << name_string << "'";
      continue;
    }

    // Create the animation and insert it into our map of currently active
    // animations.
    InternalAnimationMap::iterator inserted =
        animations_
            .insert(std::make_pair(
                name_string,
                Animation(
                    name_string, keyframes, current_time,
                    GetTimeValue(i, style.animation_delay()),
                    GetTimeValue(i, style.animation_duration()),
                    GetFillMode(i, style.animation_fill_mode()),
                    GetIterationCount(i, style.animation_iteration_count()),
                    GetDirection(i, style.animation_direction()),
                    GetTimingFunction(i, style.animation_timing_function()))))
            .first;
    if (event_handler_) {
      event_handler_->OnAnimationStarted(inserted->second);
    }

    animations_modified = true;
  }

  // Finally check for any animations that are now ended.
  std::vector<std::string> animations_to_end;
  for (InternalAnimationMap::iterator iter = animations_.begin();
       iter != animations_.end(); ++iter) {
    if (declared_animation_set.find(iter->first) ==
        declared_animation_set.end()) {
      // If the animation used to be playing, but it no longer appears in the
      // list of declared animations, then it has ended and we should mark it
      // as such.
      if (event_handler_) {
        event_handler_->OnAnimationRemoved(iter->second);
      }
      animations_to_end.push_back(iter->first);
    }
  }
  if (!animations_to_end.empty()) {
    for (std::vector<std::string>::iterator iter = animations_to_end.begin();
         iter != animations_to_end.end(); ++iter) {
      animations_.erase(*iter);
    }

    animations_modified = true;
  }

  return animations_modified;
}

}  // namespace cssom
}  // namespace cobalt
