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

#include "base/time.h"
#include "cobalt/cssom/css_computed_style_data.h"
#include "cobalt/cssom/css_transition.h"
#include "cobalt/cssom/css_transition_set.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/cssom/length_value.h"
#include "cobalt/cssom/number_value.h"
#include "cobalt/cssom/property_key_list_value.h"
#include "cobalt/cssom/property_list_value.h"
#include "cobalt/cssom/rgba_color_value.h"
#include "cobalt/cssom/string_value.h"
#include "cobalt/cssom/time_list_value.h"
#include "cobalt/cssom/timing_function.h"
#include "cobalt/cssom/timing_function_list_value.h"

#include "testing/gtest/include/gtest/gtest.h"

namespace cobalt {
namespace cssom {

namespace {
scoped_refptr<TimeListValue> MakeTimeListWithSingleTime(float time_in_seconds) {
  scoped_ptr<TimeListValue::Builder> time_list(new TimeListValue::Builder());
  time_list->push_back(base::TimeDelta::FromMicroseconds(static_cast<int64>(
      time_in_seconds * base::Time::kMicrosecondsPerSecond)));
  return make_scoped_refptr(new TimeListValue(time_list.Pass()));
}

scoped_refptr<PropertyListValue> MakePropertyListWithSingleProperty(
    const scoped_refptr<PropertyValue>& property_value) {
  scoped_ptr<PropertyListValue::Builder> property_list_builder(
      new PropertyListValue::Builder());
  property_list_builder->push_back(property_value.get());
  return make_scoped_refptr(
      new PropertyListValue(property_list_builder.Pass()));
}

scoped_refptr<PropertyKeyListValue> MakePropertyNameListWithSingleProperty(
    PropertyKey property) {
  scoped_ptr<PropertyKeyListValue::Builder> property_name_list(
      new PropertyKeyListValue::Builder());
  property_name_list->push_back(property);
  return make_scoped_refptr(
      new PropertyKeyListValue(property_name_list.Pass()));
}

scoped_refptr<TimingFunctionListValue> MakeTimingFunctionWithSingleProperty(
    const scoped_refptr<TimingFunction>& timing_function) {
  scoped_ptr<TimingFunctionListValue::Builder> timing_function_list(
      new TimingFunctionListValue::Builder());
  timing_function_list->push_back(timing_function);
  return make_scoped_refptr(
      new TimingFunctionListValue(timing_function_list.Pass()));
}

scoped_refptr<CSSComputedStyleData> CreateTestComputedData() {
  scoped_refptr<CSSComputedStyleData> initial_data = new CSSComputedStyleData();

  initial_data->set_background_color(new RGBAColorValue(0xffffffff));
  initial_data->set_color(new RGBAColorValue(0x00000000));
  initial_data->set_display(KeywordValue::GetBlock());
  initial_data->set_font_family(
      MakePropertyListWithSingleProperty(new StringValue("Roboto")));
  initial_data->set_font_size(new LengthValue(16, kPixelsUnit));
  initial_data->set_height(new LengthValue(400, kPixelsUnit));
  initial_data->set_opacity(new NumberValue(0.5f));
  initial_data->set_width(new LengthValue(400, kPixelsUnit));
  initial_data->set_transform(KeywordValue::GetNone());
  initial_data->set_transition_delay(MakeTimeListWithSingleTime(0.0f));
  initial_data->set_transition_duration(MakeTimeListWithSingleTime(0.0f));
  initial_data->set_transition_property(
      MakePropertyNameListWithSingleProperty(kAllProperty));
  initial_data->set_transition_timing_function(
      MakeTimingFunctionWithSingleProperty(TimingFunction::GetLinear()));

  return initial_data;
}
}  // namespace

class TransitionSetTest : public testing::Test {
 public:
  TransitionSetTest() {
    // Initialize start and end styles to the same data.
    start_ = CreateTestComputedData();
    end_ = CreateTestComputedData();
  }

 protected:
  scoped_refptr<CSSComputedStyleData> start_;
  scoped_refptr<CSSComputedStyleData> end_;
};

TEST_F(TransitionSetTest, TransitionSetStartsEmpty) {
  TransitionSet transition_set;
  EXPECT_TRUE(transition_set.empty());
}

TEST_F(TransitionSetTest, TransitionPropertyOfAllGeneratesATransition) {
  end_->set_background_color(new RGBAColorValue(0x00000000));
  end_->set_transition_duration(MakeTimeListWithSingleTime(1.0f));
  end_->set_transition_property(
      MakePropertyNameListWithSingleProperty(kAllProperty));

  TransitionSet transition_set;
  transition_set.UpdateTransitions(base::TimeDelta(), *start_, *end_);

  EXPECT_FALSE(transition_set.empty());
  EXPECT_TRUE(
      transition_set.GetTransitionForProperty(kBackgroundColorProperty));
}

TEST_F(TransitionSetTest,
       TransitionPropertyOfSpecificValueGeneratesATransition) {
  end_->set_background_color(new RGBAColorValue(0x00000000));
  end_->set_transition_duration(MakeTimeListWithSingleTime(1.0f));
  end_->set_transition_property(
      MakePropertyNameListWithSingleProperty(kBackgroundColorProperty));

  TransitionSet transition_set;
  transition_set.UpdateTransitions(base::TimeDelta(), *start_, *end_);

  EXPECT_FALSE(transition_set.empty());
  EXPECT_TRUE(
      transition_set.GetTransitionForProperty(kBackgroundColorProperty));
}

TEST_F(TransitionSetTest, TransitionPropertyOfNoneGeneratesNoTransition) {
  end_->set_background_color(new RGBAColorValue(0x00000000));
  end_->set_transition_duration(MakeTimeListWithSingleTime(1.0f));
  end_->set_transition_property(KeywordValue::GetNone());

  TransitionSet transition_set;
  transition_set.UpdateTransitions(base::TimeDelta(), *start_, *end_);

  EXPECT_TRUE(transition_set.empty());
}

TEST_F(TransitionSetTest, TransitionDurationOfZeroGeneratesNoTransition) {
  end_->set_background_color(new RGBAColorValue(0x00000000));
  end_->set_transition_duration(MakeTimeListWithSingleTime(0.0f));
  end_->set_transition_property(
      MakePropertyNameListWithSingleProperty(kBackgroundColorProperty));

  TransitionSet transition_set;
  transition_set.UpdateTransitions(base::TimeDelta(), *start_, *end_);

  EXPECT_TRUE(transition_set.empty());
  EXPECT_EQ(static_cast<Transition*>(NULL),
            transition_set.GetTransitionForProperty(kBackgroundColorProperty));
}

TEST_F(TransitionSetTest, NoStyleChangesGeneratesNoTransitions) {
  end_->set_transition_duration(MakeTimeListWithSingleTime(1.0f));
  end_->set_transition_property(
      MakePropertyNameListWithSingleProperty(kBackgroundColorProperty));

  TransitionSet transition_set;
  transition_set.UpdateTransitions(base::TimeDelta(), *start_, *end_);

  EXPECT_TRUE(transition_set.empty());
}

TEST_F(TransitionSetTest, TransitionDelayIsAccountedFor) {
  end_->set_background_color(new RGBAColorValue(0x00000000));
  end_->set_transition_delay(MakeTimeListWithSingleTime(1.0f));
  end_->set_transition_duration(MakeTimeListWithSingleTime(1.0f));
  end_->set_transition_property(
      MakePropertyNameListWithSingleProperty(kBackgroundColorProperty));

  TransitionSet transition_set;
  transition_set.UpdateTransitions(base::TimeDelta(), *start_, *end_);

  const Transition* transition =
      transition_set.GetTransitionForProperty(kBackgroundColorProperty);
  ASSERT_TRUE(transition);
  EXPECT_EQ(base::TimeDelta::FromSeconds(1), transition->delay());
}

// Here we start testing that the produced transitions are actually
// transitioning a given element correctly.  We use background color since it is
// the first animatable property we have available when these tests were
// written.
namespace {
void CheckTransitionsEqual(const Transition& a, const Transition& b) {
  EXPECT_TRUE(a.start_value()->Equals(*b.start_value()));
  EXPECT_TRUE(a.end_value()->Equals(*b.end_value()));
  EXPECT_TRUE(a.reversing_adjusted_start_value()->Equals(
      *b.reversing_adjusted_start_value()));

  const float kErrorEpsilon = 0.00015f;

  EXPECT_NEAR(a.duration().InSecondsF(), b.duration().InSecondsF(),
              kErrorEpsilon);
  EXPECT_NEAR(a.delay().InSecondsF(), b.delay().InSecondsF(), kErrorEpsilon);
  EXPECT_EQ(a.start_time(), b.start_time());
  EXPECT_EQ(a.target_property(), b.target_property());
  EXPECT_NEAR(a.reversing_shortening_factor(), b.reversing_shortening_factor(),
              kErrorEpsilon);
}
}  // namespace

TEST_F(TransitionSetTest, TransitionSetProducesValidFirstTransition) {
  end_->set_background_color(new RGBAColorValue(0x00000000));
  end_->set_transition_duration(MakeTimeListWithSingleTime(1.0f));
  end_->set_transition_property(
      MakePropertyNameListWithSingleProperty(kAllProperty));

  TransitionSet transition_set;
  transition_set.UpdateTransitions(base::TimeDelta(), *start_, *end_);

  EXPECT_FALSE(transition_set.empty());
  const Transition* transition =
      transition_set.GetTransitionForProperty(kBackgroundColorProperty);
  ASSERT_TRUE(transition);

  Transition expected_transition(
      kBackgroundColorProperty, new RGBAColorValue(0xffffffff),
      new RGBAColorValue(0x00000000), base::TimeDelta(),
      base::TimeDelta::FromSeconds(1), base::TimeDelta(),
      TimingFunction::GetLinear(), new RGBAColorValue(0xffffffff), 1.0f);

  CheckTransitionsEqual(expected_transition, *transition);

  // The transition should remain untouched if the style remains unchanged and
  // the transition has not completed.
  transition_set.UpdateTransitions(base::TimeDelta::FromSecondsD(0.5), *end_,
                                   *end_);

  EXPECT_FALSE(transition_set.empty());
  transition =
      transition_set.GetTransitionForProperty(kBackgroundColorProperty);
  ASSERT_TRUE(transition);

  CheckTransitionsEqual(expected_transition, *transition);
}

TEST_F(TransitionSetTest, TransitionSetRemovesTransitionAfterCompletion) {
  end_->set_background_color(new RGBAColorValue(0x00000000));
  end_->set_transition_duration(MakeTimeListWithSingleTime(1.0f));
  end_->set_transition_property(
      MakePropertyNameListWithSingleProperty(kAllProperty));

  TransitionSet transition_set;
  transition_set.UpdateTransitions(base::TimeDelta(), *start_, *end_);

  EXPECT_FALSE(transition_set.empty());
  EXPECT_TRUE(
      transition_set.GetTransitionForProperty(kBackgroundColorProperty));

  transition_set.UpdateTransitions(base::TimeDelta::FromSecondsD(2.0), *end_,
                                   *end_);

  EXPECT_TRUE(transition_set.empty());
  EXPECT_EQ(static_cast<Transition*>(NULL),
            transition_set.GetTransitionForProperty(kBackgroundColorProperty));
}

TEST_F(TransitionSetTest, TransitionsFromTransitionsWork) {
  end_->set_background_color(new RGBAColorValue(0x00000000));
  end_->set_transition_duration(MakeTimeListWithSingleTime(1.0f));
  end_->set_transition_property(
      MakePropertyNameListWithSingleProperty(kAllProperty));
  scoped_refptr<CSSComputedStyleData> end2 = CreateTestComputedData();
  end2->set_background_color(new RGBAColorValue(0x000000ff));
  end2->set_transition_duration(MakeTimeListWithSingleTime(1.0f));
  end2->set_transition_property(
      MakePropertyNameListWithSingleProperty(kAllProperty));

  TransitionSet transition_set;
  transition_set.UpdateTransitions(base::TimeDelta(), *start_, *end_);
  transition_set.UpdateTransitions(base::TimeDelta::FromSecondsD(0.5), *end_,
                                   *end2);

  EXPECT_FALSE(transition_set.empty());
  const Transition* transition =
      transition_set.GetTransitionForProperty(kBackgroundColorProperty);
  ASSERT_TRUE(transition);

  CheckTransitionsEqual(
      Transition(
          kBackgroundColorProperty, new RGBAColorValue(0x80808080),
          new RGBAColorValue(0x000000ff), base::TimeDelta::FromSecondsD(0.5),
          base::TimeDelta::FromSecondsD(1.0f), base::TimeDelta(),
          TimingFunction::GetLinear(), new RGBAColorValue(0x80808080), 1.0f),
      *transition);
}

TEST_F(TransitionSetTest, ReverseTransitionsWork) {
  end_->set_background_color(new RGBAColorValue(0x00000000));
  end_->set_transition_duration(MakeTimeListWithSingleTime(1.0f));
  end_->set_transition_property(
      MakePropertyNameListWithSingleProperty(kAllProperty));
  start_->set_transition_duration(MakeTimeListWithSingleTime(1.0f));
  start_->set_transition_property(
      MakePropertyNameListWithSingleProperty(kAllProperty));

  TransitionSet transition_set;
  transition_set.UpdateTransitions(base::TimeDelta(), *start_, *end_);
  transition_set.UpdateTransitions(base::TimeDelta::FromSecondsD(0.5), *end_,
                                   *start_);

  EXPECT_FALSE(transition_set.empty());
  const Transition* transition =
      transition_set.GetTransitionForProperty(kBackgroundColorProperty);
  ASSERT_TRUE(transition);

  CheckTransitionsEqual(
      Transition(
          kBackgroundColorProperty, new RGBAColorValue(0x80808080),
          new RGBAColorValue(0xffffffff), base::TimeDelta::FromSecondsD(0.5),
          base::TimeDelta::FromSecondsD(0.5f), base::TimeDelta(),
          TimingFunction::GetLinear(), new RGBAColorValue(0x00000000), 0.5f),
      *transition);

  // Let's try reversing the transition again.
  transition_set.UpdateTransitions(base::TimeDelta::FromSecondsD(0.75), *start_,
                                   *end_);

  EXPECT_FALSE(transition_set.empty());
  transition =
      transition_set.GetTransitionForProperty(kBackgroundColorProperty);
  ASSERT_TRUE(transition);

  CheckTransitionsEqual(
      Transition(
          kBackgroundColorProperty, new RGBAColorValue(0xc0c0c0c0),
          new RGBAColorValue(0x00000000), base::TimeDelta::FromSecondsD(0.75),
          base::TimeDelta::FromSecondsD(0.75f), base::TimeDelta(),
          TimingFunction::GetLinear(), new RGBAColorValue(0xffffffff), 0.75f),
      *transition);
}

}  // namespace cssom
}  // namespace cobalt
