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

#ifndef COBALT_WEB_ANIMATIONS_ANIMATION_H_
#define COBALT_WEB_ANIMATIONS_ANIMATION_H_

#include <memory>
#include <set>

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "cobalt/script/wrappable.h"
#include "cobalt/web_animations/animation_effect_read_only.h"
#include "cobalt/web_animations/animation_timeline.h"

namespace cobalt {
namespace web_animations {

class AnimationSet;

// Animations are represented in the Web Animations API by the Animation
// interface.
//   https://www.w3.org/TR/2015/WD-web-animations-1-20150707/#the-animation-interface
//
// This class introduces levers to pause/play/reverse an animation.  The
// Animation object provides functionality for converting from timeline time
// to the animation's local time, given its current state (e.g. start time,
// is the animation paused, etc...).  Additionally, it also links to the
// underlying effect which contains the rest of the data needed to fully
// specify an effect animation.
class Animation : public script::Wrappable {
 public:
  // Most of the internal Animation information is stored here in
  // Animation::Data.  This separate Data class exists to make it possible to
  // copy Animation information out of the non-thread-safe ref-counted
  // script-wrappable Animation object.  The class BakedAnimation takes
  // advantage of the Data object by storing an independent immutable instance
  // of the animation data that does not reference script objects and can be
  // passed to other threads.
  class Data {
   public:
    Data() : playback_rate_(1.0) {}

    const base::Optional<base::TimeDelta>& start_time() const {
      return start_time_;
    }
    void set_start_time(const base::Optional<base::TimeDelta>& start_time) {
      start_time_ = start_time;
    }

    double playback_rate() const { return playback_rate_; }
    void set_playback_rate(double playback_rate) {
      playback_rate_ = playback_rate;
    }

    // Converts the animation's timeline's time into the animation's local
    // time, which takes into account this animation's start_time().
    base::Optional<base::TimeDelta> ComputeLocalTimeFromTimelineTime(
        const base::Optional<base::TimeDelta>& timeline_time) const;
    base::Optional<base::TimeDelta> ComputeTimelineTimeFromLocalTime(
        const base::Optional<base::TimeDelta>& local_time) const;

   private:
    base::Optional<base::TimeDelta> start_time_;
    double playback_rate_;
  };

  // EventHandler objects can be created via Animation::AttachEventHandler().
  // Once created, they represent the connection of a set of Animation event
  // callbacks which may get called as the animation is updated, until the
  // EventHandler is destructed.
  class EventHandler {
   public:
    EventHandler(const scoped_refptr<Animation>& animation,
                 const base::Closure& on_enter_after_phase)
        : animation_(animation), on_enter_after_phase_(on_enter_after_phase) {}

    ~EventHandler() { animation_->RemoveEventHandler(this); }

    const base::Closure& on_enter_after_phase() const {
      return on_enter_after_phase_;
    }

   private:
    // The animation we are handling events from.
    scoped_refptr<Animation> animation_;

    // Called when the Animation's effect enters the "after phase".
    base::Closure on_enter_after_phase_;
  };

  Animation(const scoped_refptr<AnimationEffectReadOnly>& effect,
            const scoped_refptr<AnimationTimeline>& timeline);

  // Web API: Animation
  const scoped_refptr<AnimationEffectReadOnly>& effect() const {
    return effect_;
  }
  void set_effect(const scoped_refptr<AnimationEffectReadOnly>& effect) {
    effect_ = effect;
  }

  const scoped_refptr<AnimationTimeline>& timeline() const { return timeline_; }
  void set_timeline(const scoped_refptr<AnimationTimeline>& timeline);

  base::Optional<double> start_time() const {
    return data_.start_time()
               ? base::Optional<double>(data_.start_time()->InMillisecondsF())
               : base::nullopt;
  }
  void set_start_time(const base::Optional<double>& start_time) {
    if (!start_time) {
      data_.set_start_time(base::nullopt);
    } else {
      data_.set_start_time(base::TimeDelta::FromMillisecondsD(*start_time));
    }
  }

  base::Optional<double> current_time() const;
  base::Optional<base::TimeDelta> current_time_as_time_delta() const;

  void set_current_time(const base::Optional<double>& current_time);

  double playback_rate() const { return data_.playback_rate(); }
  void set_playback_rate(double playback_rate) {
    data_.set_playback_rate(playback_rate);
  }

  void Cancel();
  void Finish() {}
  void Play();
  void Pause() {}
  void Reverse() {}

  // Custom, not in any spec.
  const Data& data() const { return data_; }

  // Connects a set of events (currently only the event where the Animation's
  // effect enters its "after phase") to the provided callbacks, and returns
  // an object that represents the connection.
  std::unique_ptr<EventHandler> AttachEventHandler(
      const base::Closure& on_enter_after_phase);

  DEFINE_WRAPPABLE_TYPE(Animation);
  void TraceMembers(script::Tracer* tracer) override;

 private:
  ~Animation() override;

  // This will be called by EventHandler's destructor.
  void RemoveEventHandler(EventHandler* handler);

  // This method will update all timing-based tasks based on the current state
  // of the Animation object (and all referenced objects) when this function
  // is called.
  void UpdatePendingTasks();

  // Called when the animation's effect enters its after phase.
  void OnEnterAfterPhase();

  // It is possible for an Animation to be inserted into a AnimationSet, such
  // that is not discoverable by Web APIs, so we track all our references from
  // all AnimationSets so that we can remove ourselves from them when the
  // animation is ready to destroy itself.
  void OnAddedToAnimationSet(const scoped_refptr<AnimationSet>& set);

  // Called by AnimationSet when removed from an AnimationSet.
  void OnRemovedFromAnimationSet(const scoped_refptr<AnimationSet>& set);

  scoped_refptr<AnimationEffectReadOnly> effect_;
  scoped_refptr<AnimationTimeline> timeline_;

  // A list of animation sets that contain this animation.
  std::set<scoped_refptr<AnimationSet>> contained_in_animation_sets_;

  Data data_;

  // A list of event handlers that are interested in receiving callbacks when
  // animation events occur.
  std::set<EventHandler*> event_handlers_;
  // When a specific animation event occurs, we will copy event_handlers_ into
  // this and then call each event one by one.  This way we can manage the set
  // being modified as event handlers are called.
  std::set<EventHandler*> event_handlers_being_called_;

  // When active, this task will be setup to fire after we enter the after
  // phase.
  std::unique_ptr<TimedTaskQueue::Task> on_enter_after_phase_;

  friend class EventHandler;

  // So that we can track which AnimationSets this animation is added to.
  friend class AnimationSet;

  DISALLOW_COPY_AND_ASSIGN(Animation);
};

}  // namespace web_animations
}  // namespace cobalt

#endif  // COBALT_WEB_ANIMATIONS_ANIMATION_H_
