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

#ifndef COBALT_WEB_ANIMATIONS_ANIMATION_H_
#define COBALT_WEB_ANIMATIONS_ANIMATION_H_

#include <set>

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "base/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 {

// 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.
  scoped_ptr<EventHandler> AttachEventHandler(
      const base::Closure& on_enter_after_phase);

  DEFINE_WRAPPABLE_TYPE(Animation);

 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();

  scoped_refptr<AnimationEffectReadOnly> effect_;
  scoped_refptr<AnimationTimeline> timeline_;
  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.
  scoped_ptr<TimedTaskQueue::Task> on_enter_after_phase_;

  friend class EventHandler;

  DISALLOW_COPY_AND_ASSIGN(Animation);
};

}  // namespace web_animations
}  // namespace cobalt

#endif  // COBALT_WEB_ANIMATIONS_ANIMATION_H_
