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

#include "cobalt/cssom/css_font_face_rule.h"

#include <memory>
#include <utility>

#include "cobalt/cssom/css_font_face_declaration_data.h"
#include "cobalt/cssom/css_style_sheet.h"
#include "cobalt/cssom/font_style_value.h"
#include "cobalt/cssom/font_weight_value.h"
#include "cobalt/cssom/keyword_names.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/cssom/local_src_value.h"
#include "cobalt/cssom/mutation_observer.h"
#include "cobalt/cssom/property_definitions.h"
#include "cobalt/cssom/property_list_value.h"
#include "cobalt/cssom/property_value.h"
#include "cobalt/cssom/string_value.h"
#include "cobalt/cssom/style_sheet_list.h"
#include "cobalt/cssom/testing/mock_css_parser.h"
#include "cobalt/cssom/unicode_range_value.h"
#include "cobalt/cssom/url_src_value.h"
#include "cobalt/cssom/url_value.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace cobalt {
namespace cssom {

using ::testing::_;
using ::testing::Return;

class MockMutationObserver : public MutationObserver {
 public:
  MOCK_METHOD0(OnCSSMutation, void());
};

class CSSFontFaceRuleTest : public ::testing::Test {
 protected:
  CSSFontFaceRuleTest() : css_style_sheet_(new CSSStyleSheet(&css_parser_)) {
    css_style_sheet_->SetOriginClean(true);
    StyleSheetVector style_sheets;
    style_sheets.push_back(css_style_sheet_);
    style_sheet_list_ = new StyleSheetList(style_sheets, &mutation_observer_);
  }
  ~CSSFontFaceRuleTest() override {}

  const scoped_refptr<CSSStyleSheet> css_style_sheet_;
  scoped_refptr<StyleSheetList> style_sheet_list_;
  MockMutationObserver mutation_observer_;
  testing::MockCSSParser css_parser_;
};

TEST_F(CSSFontFaceRuleTest, PropertyValueSetter) {
  scoped_refptr<CSSFontFaceRule> font_face = new CSSFontFaceRule();
  font_face->AttachToCSSStyleSheet(css_style_sheet_);

  const std::string family = "youtube-icons";

  EXPECT_CALL(
      css_parser_,
      ParsePropertyIntoDeclarationData(
          GetPropertyName(kFontFamilyProperty), family, _,
          const_cast<CSSFontFaceDeclarationData*>(font_face->data().get())));
  EXPECT_CALL(mutation_observer_, OnCSSMutation()).Times(1);

  font_face->SetPropertyValue(GetPropertyName(kFontFamilyProperty), family);
}

TEST_F(CSSFontFaceRuleTest, FamilySetter) {
  scoped_refptr<CSSFontFaceRule> font_face = new CSSFontFaceRule();
  font_face->AttachToCSSStyleSheet(css_style_sheet_);

  const std::string family = "'youtube-icons'";

  EXPECT_CALL(
      css_parser_,
      ParsePropertyIntoDeclarationData(
          GetPropertyName(kFontFamilyProperty), family, _,
          const_cast<CSSFontFaceDeclarationData*>(font_face->data().get())));
  EXPECT_CALL(mutation_observer_, OnCSSMutation()).Times(1);

  font_face->set_family(family);
}

TEST_F(CSSFontFaceRuleTest, SrcSetter) {
  scoped_refptr<CSSFontFaceRule> font_face = new CSSFontFaceRule();
  font_face->AttachToCSSStyleSheet(css_style_sheet_);

  const std::string src =
      "local(Roboto), url('../assets/icons.woff2') format('woff2')";

  EXPECT_CALL(
      css_parser_,
      ParsePropertyIntoDeclarationData(
          GetPropertyName(kSrcProperty), src, _,
          const_cast<CSSFontFaceDeclarationData*>(font_face->data().get())));
  EXPECT_CALL(mutation_observer_, OnCSSMutation()).Times(1);

  font_face->set_src(src);
}

TEST_F(CSSFontFaceRuleTest, StyleSetter) {
  scoped_refptr<CSSFontFaceRule> font_face = new CSSFontFaceRule();
  font_face->AttachToCSSStyleSheet(css_style_sheet_);

  const std::string style = kItalicKeywordName;

  EXPECT_CALL(
      css_parser_,
      ParsePropertyIntoDeclarationData(
          GetPropertyName(kFontStyleProperty), style, _,
          const_cast<CSSFontFaceDeclarationData*>(font_face->data().get())));
  EXPECT_CALL(mutation_observer_, OnCSSMutation()).Times(1);

  font_face->set_style(style);
}

TEST_F(CSSFontFaceRuleTest, WeightSetter) {
  scoped_refptr<CSSFontFaceRule> font_face = new CSSFontFaceRule();
  font_face->AttachToCSSStyleSheet(css_style_sheet_);

  const std::string weight = kBoldKeywordName;

  EXPECT_CALL(
      css_parser_,
      ParsePropertyIntoDeclarationData(
          GetPropertyName(kFontWeightProperty), weight, _,
          const_cast<CSSFontFaceDeclarationData*>(font_face->data().get())));
  EXPECT_CALL(mutation_observer_, OnCSSMutation()).Times(1);

  font_face->set_weight(weight);
}

TEST_F(CSSFontFaceRuleTest, UnicodeRangeSetter) {
  scoped_refptr<CSSFontFaceRule> font_face = new CSSFontFaceRule();
  font_face->AttachToCSSStyleSheet(css_style_sheet_);

  const std::string unicode_range = "U+???, U+100000-10FFFF";

  EXPECT_CALL(
      css_parser_,
      ParsePropertyIntoDeclarationData(
          GetPropertyName(kUnicodeRangeProperty), unicode_range, _,
          const_cast<CSSFontFaceDeclarationData*>(font_face->data().get())));
  EXPECT_CALL(mutation_observer_, OnCSSMutation()).Times(1);

  font_face->set_unicode_range(unicode_range);
}

TEST_F(CSSFontFaceRuleTest, CSSTextSetter) {
  scoped_refptr<CSSFontFaceRule> font_face = new CSSFontFaceRule();
  font_face->AttachToCSSStyleSheet(css_style_sheet_);

  std::string css_text =
      "font-family: 'youtube-icons'; "
      "src: url('../assets/icons.woff2') format('woff2')";

  EXPECT_CALL(css_parser_, ParseFontFaceDeclarationList(css_text, _))
      .WillOnce(Return(scoped_refptr<CSSFontFaceDeclarationData>()));

  font_face->set_css_text(css_text, NULL);
}

TEST_F(CSSFontFaceRuleTest, CssTextGetter) {
  scoped_refptr<StringValue> family = new StringValue("youtube-icons");

  std::unique_ptr<PropertyListValue::Builder> src_builder(
      new PropertyListValue::Builder());
  src_builder->reserve(2);
  src_builder->push_back(new LocalSrcValue("Roboto"));
  src_builder->push_back(
      new UrlSrcValue(new URLValue("'../assets/icons.woff2'"), "woff2"));
  scoped_refptr<PropertyListValue> src(
      new PropertyListValue(std::move(src_builder)));

  scoped_refptr<FontStyleValue> style = FontStyleValue::GetItalic();
  scoped_refptr<FontWeightValue> weight = FontWeightValue::GetBoldAka700();

  std::unique_ptr<PropertyListValue::Builder> unicode_range_builder(
      new PropertyListValue::Builder());
  unicode_range_builder->reserve(2);
  unicode_range_builder->push_back(new UnicodeRangeValue(0x100, 0x100));
  unicode_range_builder->push_back(new UnicodeRangeValue(0x1000, 0x2000));
  scoped_refptr<PropertyListValue> unicode_range(
      new PropertyListValue(std::move(unicode_range_builder)));

  scoped_refptr<CSSFontFaceDeclarationData> font_face_data =
      new CSSFontFaceDeclarationData();
  font_face_data->set_family(family);
  font_face_data->set_src(src);
  font_face_data->set_style(style);
  font_face_data->set_weight(weight);
  font_face_data->set_unicode_range(unicode_range);

  scoped_refptr<CSSFontFaceRule> font_face =
      new CSSFontFaceRule(font_face_data);

  EXPECT_EQ(font_face->css_text(NULL),
            "font-family: 'youtube-icons'; "
            "src: local('Roboto'), "
            "url('../assets/icons.woff2') format('woff2'); "
            "font-style: italic; "
            "font-weight: bold; "
            "unicode-range: U+100, U+1000-2000;");
}

}  // namespace cssom
}  // namespace cobalt
