/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Peter Kelly (pmk@post.com)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#ifndef Attr_h
#define Attr_h

#include "core/dom/ContainerNode.h"
#include "core/dom/QualifiedName.h"

namespace WebCore {

class CSSStyleDeclaration;
class ExceptionState;
class MutableStylePropertySet;

// Attr can have Text children
// therefore it has to be a fullblown Node. The plan
// is to dynamically allocate a textchild and store the
// resulting nodevalue in the attribute upon
// destruction. however, this is not yet implemented.

class Attr FINAL : public ContainerNode {
public:
    static PassRefPtr<Attr> create(Element*, const QualifiedName&);
    static PassRefPtr<Attr> create(Document*, const QualifiedName&, const AtomicString& value);
    virtual ~Attr();

    String name() const { return qualifiedName().toString(); }
    bool specified() const { return m_specified; }
    Element* ownerElement() const { return m_element; }

    const AtomicString& value() const;
    void setValue(const AtomicString&, ExceptionState&);
    void setValue(const AtomicString&);

    const QualifiedName& qualifiedName() const { return m_name; }

    bool isId() const;

    void setSpecified(bool specified) { m_specified = specified; }

    void attachToElement(Element*);
    void detachFromElementWithValue(const AtomicString&);

    virtual const AtomicString& localName() const OVERRIDE { return m_name.localName(); }
    virtual const AtomicString& namespaceURI() const OVERRIDE { return m_name.namespaceURI(); }
    virtual const AtomicString& prefix() const OVERRIDE { return m_name.prefix(); }

    virtual void setPrefix(const AtomicString&, ExceptionState&) OVERRIDE;

private:
    Attr(Element*, const QualifiedName&);
    Attr(Document*, const QualifiedName&, const AtomicString& value);

    void createTextChild();

    virtual String nodeName() const OVERRIDE { return name(); }
    virtual NodeType nodeType() const OVERRIDE { return ATTRIBUTE_NODE; }

    virtual String nodeValue() const OVERRIDE { return value(); }
    virtual void setNodeValue(const String&);
    virtual PassRefPtr<Node> cloneNode(bool deep = true);

    virtual bool isAttributeNode() const { return true; }
    virtual bool childTypeAllowed(NodeType) const;

    virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);

    Attribute& elementAttribute();

    // Attr wraps either an element/name, or a name/value pair (when it's a standalone Node.)
    // Note that m_name is always set, but m_element/m_standaloneValue may be null.
    Element* m_element;
    QualifiedName m_name;
    AtomicString m_standaloneValue;

    unsigned m_ignoreChildrenChanged : 31;
    bool m_specified : 1;
};

inline Attr* toAttr(Node* node)
{
    ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isAttributeNode());
    return static_cast<Attr*>(node);
}

inline const Attr* toAttr(const Node* node)
{
    ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isAttributeNode());
    return static_cast<const Attr*>(node);
}

} // namespace WebCore

#endif // Attr_h
