/*
 * 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/dom/dom_string_map.h"

#include "base/string_util.h"
#include "cobalt/dom/element.h"
#include "cobalt/dom/global_stats.h"

namespace cobalt {
namespace dom {

namespace {

const char kDataPrefix[] = "data-";
// Subtract one for nul terminator.
const size_t kDataPrefixLength = sizeof(kDataPrefix) - 1;

// See "The algorithm for getting the list of name-value pairs" at
// https://www.w3.org/TR/html5/dom.html#dom-dataset.
base::optional<std::string> TryConvertAttributeNameToPropertyName(
    const std::string& attribute_name) {
  // First five characters of attribute name should be "data-".
  if (attribute_name.compare(0, kDataPrefixLength, kDataPrefix) != 0) {
    return base::nullopt;
  }

  // For each "-" (U+002D) character in the name that is followed by
  // a lowercase ASCII letter, remove the "-" (U+002D) character and replace
  // the character that followed it by the same character converted to ASCII
  // uppercase.
  std::string property_name;
  bool preceded_by_hyphen = false;
  for (std::string::const_iterator attribute_name_iterator =
           attribute_name.begin() + kDataPrefixLength;
       attribute_name_iterator != attribute_name.end();
       ++attribute_name_iterator) {
    char attribute_name_character = *attribute_name_iterator;

    if (attribute_name_character == '-') {
      // Double hyphen in attribute name, preserve it.
      if (preceded_by_hyphen) {
        property_name += '-';
      } else {
        preceded_by_hyphen = true;
      }
      continue;
    }

    // Attribute name should not contain uppercase ASCII characters.
    if (base::ToLowerASCII(attribute_name_character) !=
        attribute_name_character) {
      return base::nullopt;
    }

    // Convert to uppercase character if preceded by hyphen.
    char property_name_character = attribute_name_character;
    if (preceded_by_hyphen) {
      preceded_by_hyphen = false;
      property_name_character = base::ToUpperASCII(property_name_character);

      // Non-letter character after hyphen, preserve the hyphen.
      if (property_name_character == attribute_name_character) {
        property_name += '-';
      }
    }

    property_name += property_name_character;
  }
  if (preceded_by_hyphen) {
    property_name += '-';
  }
  return property_name;
}

// See "The algorithm for setting names to certain values" at
// https://www.w3.org/TR/html5/dom.html#dom-dataset.
base::optional<std::string> TryConvertPropertyNameToAttributeName(
    const std::string& property_name) {
  // Insert the string "data-" at the front of attribute name.
  std::string attribute_name = kDataPrefix;

  bool preceded_by_hyphen = false;
  for (std::string::const_iterator property_name_iterator =
           property_name.begin();
       property_name_iterator != property_name.end();
       ++property_name_iterator) {
    char property_name_character = *property_name_iterator;

    // If property name contains a "-" (U+002D) character followed by
    // a lowercase ASCII letter, abort these steps.
    if (preceded_by_hyphen &&
        base::ToUpperASCII(property_name_character) !=
            property_name_character) {
      return base::nullopt;
    }

    // For each uppercase ASCII letter in name, insert a "-" (U+002D) character
    // before the character and replace the character with the same character
    // converted to ASCII lowercase.
    if (base::ToLowerASCII(property_name_character) !=
        property_name_character) {
      attribute_name += '-';
      attribute_name += base::ToLowerASCII(property_name_character);
    } else {
      attribute_name += property_name_character;
    }

    preceded_by_hyphen = property_name_character == '-';
  }
  return attribute_name;
}

}  // namespace

DOMStringMap::DOMStringMap(const scoped_refptr<Element>& element)
    : element_(element) {
  GlobalStats::GetInstance()->Add(this);
}

base::optional<std::string> DOMStringMap::AnonymousNamedGetter(
    const std::string& property_name, script::ExceptionState* exception_state) {
  base::optional<std::string> attribute_name =
      TryConvertPropertyNameToAttributeName(property_name);
  if (attribute_name) {
    return element_->GetAttribute(*attribute_name);
  } else {
    exception_state->SetSimpleException(script::kPropertySyntaxError,
                                        property_name.c_str());
    return base::nullopt;
  }
}

void DOMStringMap::AnonymousNamedSetter(
    const std::string& property_name, const std::string& value,
    script::ExceptionState* exception_state) {
  base::optional<std::string> attribute_name =
      TryConvertPropertyNameToAttributeName(property_name);
  if (attribute_name) {
    element_->SetAttribute(*attribute_name, value);
  } else {
    exception_state->SetSimpleException(script::kPropertySyntaxError,
                                        property_name.c_str());
  }
}

bool DOMStringMap::CanQueryNamedProperty(
    const std::string& property_name) const {
  base::optional<std::string> attribute_name =
      TryConvertPropertyNameToAttributeName(property_name);
  // TODO: Throw a SyntaxError if attribute name is invalid once getters and
  // setters support throwing exceptions.
  return attribute_name && element_->HasAttribute(*attribute_name);
}

void DOMStringMap::EnumerateNamedProperties(
    script::PropertyEnumerator* enumerator) {
  for (Element::AttributeMap::const_iterator
           attribute_iterator = element_->attribute_map().begin(),
           attribute_end_iterator = element_->attribute_map().end();
       attribute_iterator != attribute_end_iterator; ++attribute_iterator) {
    base::optional<std::string> property_name =
        TryConvertAttributeNameToPropertyName(attribute_iterator->first);
    if (property_name) {
      enumerator->AddProperty(*property_name);
    }
  }
}

DOMStringMap::~DOMStringMap() { GlobalStats::GetInstance()->Remove(this); }

}  // namespace dom
}  // namespace cobalt
