/*
 * 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 "cobalt/cssom/cascaded_style.h"

#include "cobalt/css_parser/parser.h"
#include "cobalt/cssom/cascade_precedence.h"
#include "cobalt/cssom/css_computed_style_data.h"
#include "cobalt/cssom/css_declaration_data.h"
#include "cobalt/cssom/css_declared_style_data.h"
#include "cobalt/cssom/css_rule_style_declaration.h"
#include "cobalt/cssom/css_style_rule.h"
#include "cobalt/cssom/css_style_sheet.h"
#include "cobalt/cssom/keyword_value.h"
#include "googleurl/src/gurl.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace cobalt {
namespace cssom {

TEST(CascadedStyleTest, PromoteToCascadedStyle) {
  scoped_ptr<css_parser::Parser> css_parser = css_parser::Parser::Create();
  scoped_refptr<CSSDeclaredStyleData> style = new CSSDeclaredStyleData();
  RulesWithCascadePrecedence rules_with_cascade_precedence;
  GURLMap property_key_to_base_url_map;

  style->SetPropertyValueAndImportance(kVerticalAlignProperty,
                                       KeywordValue::GetBottom(), true);
  style->SetPropertyValueAndImportance(kTextAlignProperty,
                                       KeywordValue::GetLeft(), false);

  // The order of cascade precedence of the following rules:
  // rule 2 > rule 3 > rule 1.

  scoped_refptr<CSSStyleRule> css_style_rule_1 =
      css_parser->ParseRule(
                    "div {"
                    "  left: 100px !important;"
                    "  right: 100px;"
                    "  width: 100px;"
                    "  height: 100px;"
                    "}",
                    base::SourceLocation("[object CascadedStyleTest]", 1, 1))
          ->AsCSSStyleRule();
  CascadePrecedence cascade_precedence_1(kNormalUserAgent);
  rules_with_cascade_precedence.push_back(
      std::make_pair(css_style_rule_1, cascade_precedence_1));

  scoped_refptr<CSSStyleRule> css_style_rule_2 =
      css_parser->ParseRule(
                    "div {"
                    "  left: 200px;"
                    "  right: 200px !important;"
                    "  width: 200px;"
                    "  height: 200px;"
                    "  vertical-align: top !important;"
                    "  text-align: center !important;"
                    "}",
                    base::SourceLocation("[object CascadedStyleTest]", 1, 1))
          ->AsCSSStyleRule();
  CascadePrecedence cascade_precedence_2(kNormalOverride);
  rules_with_cascade_precedence.push_back(
      std::make_pair(css_style_rule_2, cascade_precedence_2));

  scoped_refptr<CSSStyleRule> css_style_rule_3 =
      css_parser->ParseRule(
                    "div {"
                    "  left: 300px;"
                    "  right: 300px;"
                    "  width: 300px !important;"
                    "  height: 300px;"
                    "}",
                    base::SourceLocation("[object CascadedStyleTest]", 1, 1))
          ->AsCSSStyleRule();
  CascadePrecedence cascade_precedence_3(kNormalAuthor);
  rules_with_cascade_precedence.push_back(
      std::make_pair(css_style_rule_3, cascade_precedence_3));

  scoped_refptr<CSSComputedStyleData> computed_style = PromoteToCascadedStyle(
      style, &rules_with_cascade_precedence, &property_key_to_base_url_map);

  EXPECT_EQ(
      computed_style->left(),
      css_style_rule_1->declared_style_data()->GetPropertyValue(kLeftProperty));
  EXPECT_EQ(computed_style->right(),
            css_style_rule_2->declared_style_data()->GetPropertyValue(
                kRightProperty));
  EXPECT_EQ(computed_style->width(),
            css_style_rule_3->declared_style_data()->GetPropertyValue(
                kWidthProperty));
  EXPECT_EQ(computed_style->height(),
            css_style_rule_2->declared_style_data()->GetPropertyValue(
                kHeightProperty));
  EXPECT_EQ(computed_style->vertical_align(),
            style->GetPropertyValue(kVerticalAlignProperty));
  EXPECT_EQ(computed_style->text_align(),
            css_style_rule_2->declared_style_data()->GetPropertyValue(
                kTextAlignProperty));
}

TEST(CascadedStyleTest, PromoteToCascadedStyleWithBackgroundImage) {
  scoped_ptr<css_parser::Parser> css_parser = css_parser::Parser::Create();
  scoped_refptr<CSSDeclaredStyleData> style = new CSSDeclaredStyleData();
  RulesWithCascadePrecedence rules_with_cascade_precedence;
  GURLMap property_key_to_base_url_map;

  // The order of cascade precedence of the following rules:
  // rule 2 > rule 1.

  scoped_refptr<CSSStyleRule> css_style_rule_1 =
      css_parser->ParseRule(
                    "div {"
                    "  left: 100px !important;"
                    "  right: 100px;"
                    "}",
                    base::SourceLocation("[object CascadedStyleTest]", 1, 1))
          ->AsCSSStyleRule();
  CascadePrecedence cascade_precedence_1(kNormalUserAgent);
  rules_with_cascade_precedence.push_back(
      std::make_pair(css_style_rule_1, cascade_precedence_1));

  scoped_refptr<CSSStyleRule> css_style_rule_2 =
      css_parser->ParseRule(
                    "div {"
                    "  left: 200px;"
                    "  right: 200px !important;"
                    "  background-image: url(foo.png);"
                    "}",
                    base::SourceLocation("[object CascadedStyleTest]", 1, 1))
          ->AsCSSStyleRule();
  CascadePrecedence cascade_precedence_2(kNormalOverride);
  rules_with_cascade_precedence.push_back(
      std::make_pair(css_style_rule_2, cascade_precedence_2));

  scoped_refptr<CSSStyleSheet> parent_style_sheet(new CSSStyleSheet());
  parent_style_sheet->SetLocationUrl(GURL("https:///www.youtube.com/tv/img"));
  css_style_rule_2->set_parent_style_sheet(parent_style_sheet.get());

  scoped_refptr<CSSComputedStyleData> computed_style = PromoteToCascadedStyle(
      style, &rules_with_cascade_precedence, &property_key_to_base_url_map);

  EXPECT_EQ(
      computed_style->left(),
      css_style_rule_1->declared_style_data()->GetPropertyValue(kLeftProperty));
  EXPECT_EQ(computed_style->right(),
            css_style_rule_2->declared_style_data()->GetPropertyValue(
                kRightProperty));
  EXPECT_EQ(computed_style->background_image(),
            css_style_rule_2->declared_style_data()->GetPropertyValue(
                kBackgroundImageProperty));
  ASSERT_FALSE(property_key_to_base_url_map.empty());
  EXPECT_EQ(property_key_to_base_url_map[kBackgroundImageProperty].spec(),
            "https://www.youtube.com/tv/img");
}

TEST(CascadedStyleTest,
     PromoteToCascadedStyleWithParentStyleSheetLocationUnset) {
  scoped_ptr<css_parser::Parser> css_parser = css_parser::Parser::Create();
  scoped_refptr<CSSDeclaredStyleData> style = new CSSDeclaredStyleData();
  RulesWithCascadePrecedence rules_with_cascade_precedence;
  GURLMap property_key_to_base_url_map;
  property_key_to_base_url_map[kBackgroundImageProperty] =
      GURL("https://www.youtube.com/tv/img");

  scoped_refptr<CSSStyleRule> css_style_rule =
      css_parser->ParseRule(
                    "div {"
                    "  left: 200px;"
                    "  right: 200px !important;"
                    "  background-image: url(foo.png);"
                    "}",
                    base::SourceLocation("[object CascadedStyleTest]", 1, 1))
          ->AsCSSStyleRule();
  CascadePrecedence cascade_precedence(kNormalOverride);
  rules_with_cascade_precedence.push_back(
      std::make_pair(css_style_rule, cascade_precedence));

  scoped_refptr<CSSStyleSheet> parent_style_sheet(new CSSStyleSheet());
  css_style_rule->set_parent_style_sheet(parent_style_sheet.get());

  scoped_refptr<CSSComputedStyleData> computed_style = PromoteToCascadedStyle(
      style, &rules_with_cascade_precedence, &property_key_to_base_url_map);

  EXPECT_EQ(
      computed_style->left(),
      css_style_rule->declared_style_data()->GetPropertyValue(kLeftProperty));
  EXPECT_EQ(
      computed_style->right(),
      css_style_rule->declared_style_data()->GetPropertyValue(kRightProperty));
  EXPECT_EQ(computed_style->background_image(),
            css_style_rule->declared_style_data()->GetPropertyValue(
                kBackgroundImageProperty));
  ASSERT_FALSE(property_key_to_base_url_map.empty());
  EXPECT_EQ(property_key_to_base_url_map[kBackgroundImageProperty].spec(),
            "https://www.youtube.com/tv/img");
}

TEST(CascadedStyleTest,
     PromoteToCascadedStyleWithHigherBackgroundImagePriorityInFirstRule) {
  scoped_ptr<css_parser::Parser> css_parser = css_parser::Parser::Create();
  scoped_refptr<CSSDeclaredStyleData> style = new CSSDeclaredStyleData();
  RulesWithCascadePrecedence rules_with_cascade_precedence;
  GURLMap property_key_to_base_url_map;

  // The order of cascade precedence of the following rules:
  // rule 2 > rule 1.

  scoped_refptr<CSSStyleRule> css_style_rule_1 =
      css_parser->ParseRule(
                    "div {"
                    "  right: 100px;"
                    "  background-image: url(bar.png) !important;"
                    "}",
                    base::SourceLocation("[object CascadedStyleTest]", 1, 1))
          ->AsCSSStyleRule();
  CascadePrecedence cascade_precedence_1(kNormalUserAgent);
  rules_with_cascade_precedence.push_back(
      std::make_pair(css_style_rule_1, cascade_precedence_1));

  scoped_refptr<CSSStyleSheet> parent_style_sheet_1(new CSSStyleSheet());
  parent_style_sheet_1->SetLocationUrl(
      GURL("https:///www.youtube.com/tv/img1"));
  css_style_rule_1->set_parent_style_sheet(parent_style_sheet_1.get());

  scoped_refptr<CSSStyleRule> css_style_rule_2 =
      css_parser->ParseRule(
                    "div {"
                    "  right: 200px !important;"
                    "  background-image: url(foo.png);"
                    "}",
                    base::SourceLocation("[object CascadedStyleTest]", 1, 1))
          ->AsCSSStyleRule();
  CascadePrecedence cascade_precedence_2(kNormalOverride);
  rules_with_cascade_precedence.push_back(
      std::make_pair(css_style_rule_2, cascade_precedence_2));

  scoped_refptr<CSSStyleSheet> parent_style_sheet_2(new CSSStyleSheet());
  parent_style_sheet_2->SetLocationUrl(
      GURL("https:///www.youtube.com/tv/img2"));
  css_style_rule_2->set_parent_style_sheet(parent_style_sheet_2.get());

  scoped_refptr<CSSComputedStyleData> computed_style = PromoteToCascadedStyle(
      style, &rules_with_cascade_precedence, &property_key_to_base_url_map);

  EXPECT_EQ(computed_style->right(),
            css_style_rule_2->declared_style_data()->GetPropertyValue(
                kRightProperty));
  EXPECT_EQ(computed_style->background_image(),
            css_style_rule_1->declared_style_data()->GetPropertyValue(
                kBackgroundImageProperty));
  ASSERT_FALSE(property_key_to_base_url_map.empty());
  EXPECT_EQ(property_key_to_base_url_map[kBackgroundImageProperty].spec(),
            "https://www.youtube.com/tv/img1");
}

}  // namespace cssom
}  // namespace cobalt
