/*
 * Copyright (C) 2009 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "public/web/WebElement.h"

#include "bindings/core/v8/ExceptionState.h"
#include "core/HTMLNames.h"
#include "core/dom/Element.h"
#include "core/dom/custom/V0CustomElementProcessingStack.h"
#include "core/editing/EditingUtilities.h"
#include "core/html/TextControlElement.h"
#include "platform/graphics/Image.h"
#include "public/platform/WebRect.h"
#include "wtf/PassRefPtr.h"
#include "wtf/text/AtomicString.h"
#include "wtf/text/WTFString.h"

namespace blink {

using namespace HTMLNames;

bool WebElement::isFormControlElement() const {
  return constUnwrap<Element>()->isFormControlElement();
}

// TODO(dglazkov): Remove. Consumers of this code should use
// Node:hasEditableStyle.  http://crbug.com/612560
bool WebElement::isEditable() const {
  const Element* element = constUnwrap<Element>();

  element->document().updateStyleAndLayoutTree();
  if (hasEditableStyle(*element))
    return true;

  if (element->isTextControl()) {
    if (!toTextControlElement(element)->isDisabledOrReadOnly())
      return true;
  }

  return equalIgnoringASCIICase(element->getAttribute(roleAttr), "textbox");
}

WebString WebElement::tagName() const {
  return constUnwrap<Element>()->tagName();
}

bool WebElement::hasHTMLTagName(const WebString& tagName) const {
  // How to create                     class              nodeName localName
  // createElement('input')            HTMLInputElement   INPUT    input
  // createElement('INPUT')            HTMLInputElement   INPUT    input
  // createElementNS(xhtmlNS, 'input') HTMLInputElement   INPUT    input
  // createElementNS(xhtmlNS, 'INPUT') HTMLUnknownElement INPUT    INPUT
  const Element* element = constUnwrap<Element>();
  return HTMLNames::xhtmlNamespaceURI == element->namespaceURI() &&
         element->localName() == String(tagName).lower();
}

bool WebElement::hasAttribute(const WebString& attrName) const {
  return constUnwrap<Element>()->hasAttribute(attrName);
}

WebString WebElement::getAttribute(const WebString& attrName) const {
  return constUnwrap<Element>()->getAttribute(attrName);
}

void WebElement::setAttribute(const WebString& attrName,
                              const WebString& attrValue) {
  // TODO: Custom element callbacks need to be called on WebKit API methods that
  // mutate the DOM in any way.
  V0CustomElementProcessingStack::CallbackDeliveryScope
      deliverCustomElementCallbacks;
  unwrap<Element>()->setAttribute(attrName, attrValue,
                                  IGNORE_EXCEPTION_FOR_TESTING);
}

unsigned WebElement::attributeCount() const {
  if (!constUnwrap<Element>()->hasAttributes())
    return 0;
  return constUnwrap<Element>()->attributes().size();
}

WebString WebElement::attributeLocalName(unsigned index) const {
  if (index >= attributeCount())
    return WebString();
  return constUnwrap<Element>()->attributes().at(index).localName();
}

WebString WebElement::attributeValue(unsigned index) const {
  if (index >= attributeCount())
    return WebString();
  return constUnwrap<Element>()->attributes().at(index).value();
}

WebString WebElement::textContent() const {
  return constUnwrap<Element>()->textContent();
}

bool WebElement::hasNonEmptyLayoutSize() const {
  return constUnwrap<Element>()->hasNonEmptyLayoutSize();
}

WebRect WebElement::boundsInViewport() const {
  return constUnwrap<Element>()->boundsInViewport();
}

WebImage WebElement::imageContents() {
  if (isNull())
    return WebImage();

  return WebImage(unwrap<Element>()->imageContents());
}

WebElement::WebElement(Element* elem) : WebNode(elem) {}

DEFINE_WEB_NODE_TYPE_CASTS(WebElement, isElementNode());

WebElement& WebElement::operator=(Element* elem) {
  m_private = elem;
  return *this;
}

WebElement::operator Element*() const {
  return toElement(m_private.get());
}

}  // namespace blink
