/*
 * Copyright 2014 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 <vector>

#include "base/optional.h"
#include "cobalt/cssom/css_computed_style_data.h"
#include "cobalt/cssom/css_declared_style_data.h"
#include "cobalt/cssom/css_rule_style_declaration.h"
#include "cobalt/cssom/css_style_sheet.h"

namespace cobalt {
namespace cssom {

namespace {

void SetPropertyValuesOfHigherPrecedence(
    const scoped_refptr<const CSSDeclaredStyleData>& style,
    const CascadePrecedence& precedence_normal,
    const CascadePrecedence& precedence_important,
    base::optional<CascadePrecedence>* cascade_precedences,
    scoped_refptr<CSSComputedStyleData>* cascaded_style,
    bool* background_image_refreshed) {
  const CSSDeclaredStyleData::PropertyValues& property_values =
      style->declared_property_values();
  for (CSSDeclaredStyleData::PropertyValues::const_iterator
           property_value_iterator = property_values.begin();
       property_value_iterator != property_values.end();
       ++property_value_iterator) {
    const PropertyKey& key = property_value_iterator->first;
    DCHECK_GT(key, kNoneProperty);
    DCHECK_LE(key, kMaxLonghandPropertyKey);

    const CascadePrecedence& precedence =
        style->IsDeclaredPropertyImportant(key) ? precedence_important
                                                : precedence_normal;
    if (!(cascade_precedences[key]) ||
        *(cascade_precedences[key]) < precedence) {
      cascade_precedences[key] = precedence;
      (*cascaded_style)->SetPropertyValue(key, property_value_iterator->second);
      if (kBackgroundImageProperty == key) {
        *background_image_refreshed = true;
      }
    }
  }
}

}  // namespace

scoped_refptr<CSSComputedStyleData> PromoteToCascadedStyle(
    const scoped_refptr<const CSSDeclaredStyleData>& inline_style,
    RulesWithCascadePrecedence* matching_rules,
    GURLMap* property_key_to_base_url_map) {
  scoped_refptr<CSSComputedStyleData> cascaded_style(
      new CSSComputedStyleData());

  // A sparse vector of CascadePrecedence values for all possible property
  // values.
  base::optional<CascadePrecedence>
      cascade_precedences[static_cast<size_t>(kNumLonghandProperties)];

  if (inline_style) {
    const CascadePrecedence precedence_normal =
        CascadePrecedence(kImportantMin);
    const CascadePrecedence precedence_important =
        CascadePrecedence(kImportantMax);
    bool background_image_refreshed = false;
    SetPropertyValuesOfHigherPrecedence(
        inline_style, precedence_normal, precedence_important,
        cascade_precedences, &cascaded_style, &background_image_refreshed);
  }

  if (!matching_rules->empty()) {
    for (RulesWithCascadePrecedence::const_iterator rule_iterator =
             matching_rules->begin();
         rule_iterator != matching_rules->end(); ++rule_iterator) {
      const scoped_refptr<const CSSDeclaredStyleData>& declared_style =
          rule_iterator->first->declared_style_data();
      if (declared_style) {
        const CascadePrecedence& precedence_normal = rule_iterator->second;
        CascadePrecedence precedence_important = rule_iterator->second;
        precedence_important.SetImportant();
        bool background_image_refreshed = false;
        SetPropertyValuesOfHigherPrecedence(
            declared_style, precedence_normal, precedence_important,
            cascade_precedences, &cascaded_style, &background_image_refreshed);

        if (background_image_refreshed) {
          const scoped_refptr<CSSStyleSheet>& parent_style_sheet =
              rule_iterator->first->parent_style_sheet();
          if (parent_style_sheet &&
              parent_style_sheet->LocationUrl().is_valid()) {
            DCHECK(property_key_to_base_url_map);
            (*property_key_to_base_url_map)[kBackgroundImageProperty] =
                parent_style_sheet->LocationUrl();
          }
        }
      }
    }
  }
  return cascaded_style;
}

}  // namespace cssom
}  // namespace cobalt
