/*
 * 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_CSSOM_CSS_TRANSITION_SET_H_
#define COBALT_CSSOM_CSS_TRANSITION_SET_H_

#include <map>

#include "base/basictypes.h"
#include "base/optional.h"
#include "base/time.h"
#include "cobalt/cssom/css_transition.h"
#include "cobalt/cssom/property_definitions.h"

namespace cobalt {
namespace cssom {

class CSSComputedStyleData;
class PropertyValue;

// Maintains a mapping from the set of all unique CSS style properties to
// active transitions.  Not all style properties may have active transitions.
// This class is used to maintain persistance of active transitions and is
// expected to be modified over time as events such as CSS style modifications
// occur.
class TransitionSet {
 public:
  // An EventHandler object can be supplied to the TransitionSet upon
  // construction to have TransitionSet update a caller as it internally updates
  // its set of active transitions on each call to UpdateTransitions().  This
  // is useful as it can provide an external observer (e.g. such as an adapter
  // from CSS Transitions to the Web Animations API) the opportunity to take
  // action based on transition start/end events.
  class EventHandler {
   public:
    virtual ~EventHandler() {}
    // Called when a transition is starting, either freshly introduced or
    // replacing an existing transition.
    virtual void OnTransitionStarted(const Transition& transition) = 0;

    // Called when a transition is removed, either because it has finished, or
    // because it was replaced (in which case OnTransitionStarted() will be
    // called with the replacement immediately after this).
    virtual void OnTransitionRemoved(const Transition& transition) = 0;
  };

  explicit TransitionSet(EventHandler* event_handler = NULL);

  // Helper function to get a const reference to a global empty transition set.
  static const TransitionSet* EmptyTransitionSet();

  // Given a source and destination CSS Style Declarations (presumably applied
  // to an HTML element), updates all current transitions to reflect the new
  // state.  This may mean removing transitions that were canceled or
  // completed, updating existing transitions with new values, or creating new
  // transitions.  The implementation of this method is defined here:
  //   https://www.w3.org/TR/2013/WD-css3-transitions-20131119/#starting
  void UpdateTransitions(const base::TimeDelta& current_time,
                         const CSSComputedStyleData& source,
                         const CSSComputedStyleData& destination);

  // Given the name of a property, returns the active transition corresponding
  // to it.  If no transition currently exists for this property, this method
  // returns NULL.
  const Transition* GetTransitionForProperty(PropertyKey property) const;

  // Returns true if there are no animations in this animation set.
  bool empty() const { return transitions_.IsEmpty(); }

 private:
  void UpdateTransitionForProperty(
      PropertyKey property, const base::TimeDelta& current_time,
      const scoped_refptr<PropertyValue>& source_value,
      const scoped_refptr<PropertyValue>& destination_value,
      const CSSComputedStyleData& transition_style);

  // We define a TransitionMap (from CSS property to Transition object) here to
  // host our set of active transitions, and additionally manage the firing
  // of transition begin/end events.
  class TransitionMap {
   public:
    explicit TransitionMap(EventHandler* event_handler);
    ~TransitionMap();

    const Transition* GetTransitionForProperty(PropertyKey property) const;
    bool IsEmpty() const { return transitions_.empty(); }

    // Adds or replaces an existing transition in the map.
    void UpdateTransitionForProperty(PropertyKey property,
                                     const Transition& transition);

    // Removes an existing transition from the map.  The transition must
    // already exist in the map.
    void RemoveTransitionForProperty(PropertyKey property);

    typedef std::map<PropertyKey, Transition> InternalTransitionMap;
    const InternalTransitionMap& GetInternalMap() const { return transitions_; }

   private:
    EventHandler* event_handler_;
    InternalTransitionMap transitions_;
  };

  TransitionMap transitions_;

  DISALLOW_COPY_AND_ASSIGN(TransitionSet);
};

}  // namespace cssom
}  // namespace cobalt

#endif  // COBALT_CSSOM_CSS_TRANSITION_SET_H_
