/*
 * 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 "base/logging.h"
#include "cobalt/web_animations/animation.h"
#include "cobalt/web_animations/keyframe_effect_read_only.h"

namespace cobalt {
namespace web_animations {

Animation::Animation(const scoped_refptr<AnimationEffectReadOnly>& effect,
                     const scoped_refptr<AnimationTimeline>& timeline)
    : effect_(effect) {
  const KeyframeEffectReadOnly* keyframe_effect =
      base::polymorphic_downcast<const KeyframeEffectReadOnly*>(effect.get());
  if (keyframe_effect) {
    keyframe_effect->target()->Register(this);
  }
  set_timeline(timeline);
}

void Animation::set_timeline(const scoped_refptr<AnimationTimeline>& timeline) {
  if (timeline_) {
    timeline_->Deregister(this);
  }

  if (timeline) {
    timeline->Register(this);
  }

  timeline_ = timeline;
}

// https://www.w3.org/TR/2015/WD-web-animations-1-20150707/#playing-an-animation-section
void Animation::Play() {
  // This is currently a simplified version of steps 8.2.
  if (timeline_) {
    DCHECK(timeline_->current_time());
    if (!data_.start_time()) {
      set_start_time(timeline_->current_time());
    }
  }

  UpdatePendingTasks();
}

// https://www.w3.org/TR/2015/WD-web-animations-1-20150707/#cancel-an-animation
void Animation::Cancel() {
  // 5.  Make animation's start time unresolved.
  data_.set_start_time(base::nullopt);

  UpdatePendingTasks();
}

base::optional<base::TimeDelta> Animation::current_time_as_time_delta() const {
  if (!timeline_) {
    return base::nullopt;
  }

  return data_.ComputeLocalTimeFromTimelineTime(
      timeline_->current_time_as_time_delta());
}

// https://www.w3.org/TR/2015/WD-web-animations-1-20150707/#the-current-time-of-an-animation
base::optional<double> Animation::current_time() const {
  base::optional<base::TimeDelta> current_time = current_time_as_time_delta();
  return current_time ? base::optional<double>(current_time->InMillisecondsF())
                      : base::nullopt;
}

namespace {
base::TimeDelta ScaleTime(const base::TimeDelta& time, double scale) {
  return base::TimeDelta::FromMillisecondsD(time.InMillisecondsF() * scale);
}
}  // namespace

// https://www.w3.org/TR/2015/WD-web-animations-1-20150707/#the-current-time-of-an-animation
base::optional<base::TimeDelta>
Animation::Data::ComputeLocalTimeFromTimelineTime(
    const base::optional<base::TimeDelta>& timeline_time) const {
  // TODO: Take into account the hold time.
  if (!timeline_time || !start_time_) {
    return base::nullopt;
  }

  return ScaleTime(*timeline_time - *start_time_, playback_rate_);
}

base::optional<base::TimeDelta>
Animation::Data::ComputeTimelineTimeFromLocalTime(
    const base::optional<base::TimeDelta>& local_time) const {
  if (!start_time_ || !local_time) {
    return base::nullopt;
  }

  if (local_time == base::TimeDelta::Max()) {
    return base::TimeDelta::Max();
  }

  return ScaleTime(*local_time, 1.0 / playback_rate_) + *start_time_;
}

// https://www.w3.org/TR/2015/WD-web-animations-1-20150707/#setting-the-current-time-of-an-animation
void Animation::set_current_time(const base::optional<double>& current_time) {
  UNREFERENCED_PARAMETER(current_time);
  NOTIMPLEMENTED();
}

Animation::~Animation() {
  const KeyframeEffectReadOnly* keyframe_effect =
      base::polymorphic_downcast<const KeyframeEffectReadOnly*>(effect_.get());
  if (timeline_) {
    timeline_->Deregister(this);
  }
  if (keyframe_effect) {
    keyframe_effect->target()->Deregister(this);
  }
}

void Animation::UpdatePendingTasks() {
  if (!effect_) {
    return;
  }

  base::TimeDelta end_time_local =
      effect_->timing()->data().time_until_after_phase(base::TimeDelta());

  base::optional<base::TimeDelta> end_time_timeline =
      data_.ComputeTimelineTimeFromLocalTime(end_time_local);

  // If the local time is unresolved, then we cannot know when we will enter
  // the "after phase".
  if (end_time_timeline &&
      *end_time_timeline >= *timeline_->current_time_as_time_delta() &&
      *end_time_timeline != base::TimeDelta::Max()) {
    // Setup the "upon entering the after phase" event to fire at the
    // specified timeline time.
    on_enter_after_phase_ = timeline_->QueueTask(
        *end_time_timeline,
        base::Bind(&Animation::OnEnterAfterPhase, base::Unretained(this)));
  } else {
    // We are already in the after phase, so clear this task.
    on_enter_after_phase_.reset();
  }
}

void Animation::OnEnterAfterPhase() {
  if (event_handlers_.empty()) return;

  // Since this method is called via callback, and since one of the
  // event handlers it calls may result in the destruction of the
  // animation, the following line ensures the animation stays constructed
  // until we are done firing the callbacks.
  scoped_refptr<Animation> this_animation(this);

  // We start by making a copy of the set of event handlers we will call, in
  // case this set is modified while we are calling them.
  event_handlers_being_called_ = event_handlers_;

  // When we enter the after phase, let all registered event handlers know.
  while (!event_handlers_being_called_.empty()) {
    EventHandler* event_handler = *event_handlers_being_called_.begin();
    event_handlers_being_called_.erase(event_handlers_being_called_.begin());

    if (!event_handler->on_enter_after_phase().is_null()) {
      event_handler->on_enter_after_phase().Run();
    }
  }
}

scoped_ptr<Animation::EventHandler> Animation::AttachEventHandler(
    const base::Closure& on_enter_after_phase) {
  // Attaches an event handler to this animation and returns a handle to it.
  scoped_ptr<Animation::EventHandler> event_handler(
      new Animation::EventHandler(this, on_enter_after_phase));

  event_handlers_.insert(event_handler.get());

  return event_handler.Pass();
}

void Animation::RemoveEventHandler(EventHandler* handler) {
  // Called when the EventHandler object is destructed, this "deregisters"
  // the event handler from the Animation's event handler set.
  std::set<EventHandler*>::iterator found = event_handlers_.find(handler);
  DCHECK(found != event_handlers_.end());

  event_handlers_.erase(found);

  // If the event handler is while we are dispatching a list of event handlers,
  // then remove it from that list as well so that we don't call it.
  event_handlers_being_called_.erase(handler);
}

}  // namespace web_animations
}  // namespace cobalt
