// 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_CSSOM_TIMING_FUNCTION_H_
#define COBALT_CSSOM_TIMING_FUNCTION_H_

#include <string>

#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/strings/stringprintf.h"
#include "cobalt/base/polymorphic_equatable.h"
#include "cobalt/cssom/keyword_names.h"
#include "cobalt/math/cubic_bezier.h"

namespace cobalt {
namespace cssom {

// The TimingFunction class represents a timing function CSS property value
// that transforms time (from 0 to 1) into animation progress (where 0
// means the beginning and 1 means the end).  Since CSS provides keywords
// for common timing function parameters, these specific timing functions also
// have getter methods provided here.
// More information on CSS timing functions can be found in the specification:
//   https://www.w3.org/TR/css3-transitions/#transition-timing-function-property
class TimingFunction : public base::RefCountedThreadSafe<TimingFunction>,
                       public base::PolymorphicEquatable {
 public:
  // Transforms a time value (x) into an animation progress value (the return
  // value).
  virtual float Evaluate(float x) const = 0;

  // Functions to retreive specific timing functions that are named by CSS
  // keywords.
  static const scoped_refptr<TimingFunction>& GetEase();
  static const scoped_refptr<TimingFunction>& GetEaseIn();
  static const scoped_refptr<TimingFunction>& GetEaseInOut();
  static const scoped_refptr<TimingFunction>& GetEaseOut();
  static const scoped_refptr<TimingFunction>& GetLinear();
  static const scoped_refptr<TimingFunction>& GetStepEnd();
  static const scoped_refptr<TimingFunction>& GetStepStart();

  virtual std::string ToString() = 0;

 protected:
  virtual ~TimingFunction() {}

  friend class base::RefCountedThreadSafe<TimingFunction>;
};

// A cubic bezier timing function is parameterized by two 2D control points, one
// at position (0, 0) and the other at position (1, 1).
// Note that this is not a 1D bezier curve, rather it is the function defined by
// drawing a 2D bezier curve to act as the graph of a 1D function.  The only
// reason this function maps each x value to a *unique* y value is because of
// restrictions on the input control points.  The defined function is NOT a
// polynomial (it contains square-root and cube-root terms).
class CubicBezierTimingFunction : public TimingFunction {
 public:
  CubicBezierTimingFunction(float p1_x, float p1_y, float p2_x, float p2_y)
      : cubic_bezier_(p1_x, p1_y, p2_x, p2_y) {}

  float Evaluate(float x) const override;

  std::string ToString() override;

  bool operator==(const CubicBezierTimingFunction& other) const {
    return cubic_bezier_ == other.cubic_bezier_;
  }

  DEFINE_POLYMORPHIC_EQUATABLE_TYPE(CubicBezierTimingFunction);

 protected:
  ~CubicBezierTimingFunction() override {}

 private:
  math::CubicBezier cubic_bezier_;
};

// A stepping timing function is a piecewise constant function that progress
// towards the result in discrete steps.
class SteppingTimingFunction : public TimingFunction {
 public:
  // When should the step in progress occur, at the starts of the step intervals
  // or the ends of the step intervals.
  enum ValueChangeLocation {
    kStart,
    kEnd,
  };

  SteppingTimingFunction(int number_of_steps,
                         ValueChangeLocation value_change_location)
      : number_of_steps_(number_of_steps),
        value_change_location_(value_change_location) {
    DCHECK_LT(0, number_of_steps_);
  }

  float Evaluate(float x) const override;

  std::string ToString() override;

  bool operator==(const SteppingTimingFunction& other) const {
    return number_of_steps_ == other.number_of_steps_ &&
           value_change_location_ == other.value_change_location_;
  }

  DEFINE_POLYMORPHIC_EQUATABLE_TYPE(SteppingTimingFunction);

 protected:
  ~SteppingTimingFunction() override{};

 private:
  int number_of_steps_;
  ValueChangeLocation value_change_location_;
};

}  // namespace cssom
}  // namespace cobalt

#endif  // COBALT_CSSOM_TIMING_FUNCTION_H_
