// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_GFX_ANIMATION_MULTI_ANIMATION_H_
#define UI_GFX_ANIMATION_MULTI_ANIMATION_H_

#include <stddef.h>

#include <vector>

#include "base/macros.h"
#include "ui/gfx/animation/animation.h"
#include "ui/gfx/animation/tween.h"

namespace gfx {

// MultiAnimation is an animation that consists of a number of sub animations.
// To create a MultiAnimation pass in the parts, invoke Start() and the delegate
// is notified as the animation progresses. By default MultiAnimation runs until
// Stop is invoked, see |set_continuous()| for details.
class GFX_EXPORT MultiAnimation : public Animation {
 public:
  // Defines part of the animation. Each part consists of the following:
  //
  // time_ms: the time of the part.
  // start_time_ms: the amount of time to offset this part by when calculating
  // the percented completed.
  // end_time_ms: the end time used to calculate the percentange completed.
  //
  // In most cases |start_time_ms| = 0 and |end_time_ms| = |time_ms|. But you
  // can adjust the start/end for different effects. For example, to run a part
  // for 200ms with a % between .25 and .75 use the following three values: 200,
  // 100, 400.
  struct Part {
    Part() : time_ms(0), start_time_ms(0), end_time_ms(0), type(Tween::ZERO) {}
    Part(int time_ms, Tween::Type type)
        : time_ms(time_ms),
          start_time_ms(0),
          end_time_ms(time_ms),
          type(type) {}

    int time_ms;
    int start_time_ms;
    int end_time_ms;
    Tween::Type type;
  };

  typedef std::vector<Part> Parts;

  MultiAnimation(const Parts& parts, base::TimeDelta timer_interval);
  ~MultiAnimation() override;

  // Default interval.
  static base::TimeDelta GetDefaultTimerInterval();

  // Sets whether the animation continues after it reaches the end. If true, the
  // animation runs until explicitly stopped. The default is true.
  void set_continuous(bool continuous) { continuous_ = continuous; }

  // Returns the current value. The current value for a MultiAnimation is
  // determined from the tween type of the current part.
  double GetCurrentValue() const override;

  // Returns the index of the current part.
  size_t current_part_index() const { return current_part_index_; }

 protected:
  // Animation overrides.
  void Step(base::TimeTicks time_now) override;
  void SetStartTime(base::TimeTicks start_time) override;

 private:
  // Returns the part containing the specified time. |time_ms| is reset to be
  // relative to the part containing the time and |part_index| the index of the
  // part.
  const Part& GetPart(int* time_ms, size_t* part_index);

  // The parts that make up the animation.
  const Parts parts_;

  // Total time of all the parts.
  const int cycle_time_ms_;

  // Current value for the animation.
  double current_value_;

  // Index of the current part.
  size_t current_part_index_;

  // See description above setter.
  bool continuous_;

  DISALLOW_COPY_AND_ASSIGN(MultiAnimation);
};

}  // namespace gfx

#endif  // UI_GFX_ANIMATION_MULTI_ANIMATION_H_
