/*
 * Copyright (C) 2013, 2014 Apple 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
 */

#pragma once

#include "Attribute.h"
#include "SpaceSplitString.h"
#include <wtf/RefCounted.h>
#include <wtf/TypeCasts.h>

namespace WebCore {

class Attr;
class ShareableElementData;
class StyleProperties;
class UniqueElementData;

class AttributeConstIterator {
public:
    AttributeConstIterator(const Attribute* array, unsigned offset)
        : m_array(array)
        , m_offset(offset)
    {
    }

    const Attribute& operator*() const { return m_array[m_offset]; }
    const Attribute* operator->() const { return &m_array[m_offset]; }
    AttributeConstIterator& operator++() { ++m_offset; return *this; }

    bool operator==(const AttributeConstIterator& other) const { return m_offset == other.m_offset; }
    bool operator!=(const AttributeConstIterator& other) const { return !(*this == other); }

private:
    const Attribute* m_array;
    unsigned m_offset;
};

class AttributeIteratorAccessor {
public:
    AttributeIteratorAccessor(const Attribute* array, unsigned size)
        : m_array(array)
        , m_size(size)
    {
    }

    AttributeConstIterator begin() const { return AttributeConstIterator(m_array, 0); }
    AttributeConstIterator end() const { return AttributeConstIterator(m_array, m_size); }

    unsigned attributeCount() const { return m_size; }

private:
    const Attribute* m_array;
    unsigned m_size;
};

DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(ElementData);
class ElementData : public RefCounted<ElementData> {
    WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(ElementData);
public:
    // Override RefCounted's deref() to ensure operator delete is called on
    // the appropriate subclass type.
    void deref();

    static const unsigned attributeNotFound = static_cast<unsigned>(-1);

    void setClassNames(SpaceSplitString&& classNames) const { m_classNames = WTFMove(classNames); }
    const SpaceSplitString& classNames() const { return m_classNames; }
    static ptrdiff_t classNamesMemoryOffset() { return OBJECT_OFFSETOF(ElementData, m_classNames); }

    const AtomString& idForStyleResolution() const { return m_idForStyleResolution; }
    static ptrdiff_t idForStyleResolutionMemoryOffset() { return OBJECT_OFFSETOF(ElementData, m_idForStyleResolution); }
    void setIdForStyleResolution(const AtomString& newId) const { m_idForStyleResolution = newId; }

    const StyleProperties* inlineStyle() const { return m_inlineStyle.get(); }
    const StyleProperties* presentationalHintStyle() const;

    unsigned length() const;
    bool isEmpty() const { return !length(); }

    AttributeIteratorAccessor attributesIterator() const;
    const Attribute& attributeAt(unsigned index) const;
    const Attribute* findAttributeByName(const QualifiedName&) const;
    unsigned findAttributeIndexByName(const QualifiedName&) const;
    unsigned findAttributeIndexByName(const AtomString& name, bool shouldIgnoreAttributeCase) const;
    const Attribute* findLanguageAttribute() const;

    bool hasID() const { return !m_idForStyleResolution.isNull(); }
    bool hasClass() const { return !m_classNames.isEmpty(); }
    bool hasName() const { return m_arraySizeAndFlags & s_flagHasNameAttribute; }

    bool isEquivalent(const ElementData* other) const;

    bool isUnique() const { return m_arraySizeAndFlags & s_flagIsUnique; }
    static uint32_t isUniqueFlag() { return s_flagIsUnique; }

    static ptrdiff_t arraySizeAndFlagsMemoryOffset() { return OBJECT_OFFSETOF(ElementData, m_arraySizeAndFlags); }
    static inline uint32_t styleAttributeIsDirtyFlag() { return s_flagStyleAttributeIsDirty; }
    static uint32_t animatedSVGAttributesAreDirtyFlag() { return s_flagAnimatedSVGAttributesAreDirty; }

    static uint32_t arraySizeOffset() { return s_flagCount; }

private:
    mutable uint32_t m_arraySizeAndFlags;

    static const uint32_t s_arraySize = 27;
    static const uint32_t s_flagCount = 5;
    static const uint32_t s_flagIsUnique = 1;
    static const uint32_t s_flagHasNameAttribute = 1 << 1;
    static const uint32_t s_flagPresentationalHintStyleIsDirty = 1 << 2;
    static const uint32_t s_flagStyleAttributeIsDirty = 1 << 3;
    static const uint32_t s_flagAnimatedSVGAttributesAreDirty = 1 << 4;
    static const uint32_t s_flagsMask = (1 << s_flagCount) - 1;
    // FIXME: could the SVG specific flags go to some SVG class?

    inline void updateFlag(uint32_t flag, bool set) const
    {
        if (set)
            m_arraySizeAndFlags |= flag;
        else
            m_arraySizeAndFlags &= ~flag;
    }
    static inline uint32_t arraySizeAndFlagsFromOther(const ElementData& other, bool isUnique);

protected:
    ElementData();
    explicit ElementData(unsigned arraySize);
    ElementData(const ElementData&, bool isUnique);

    unsigned arraySize() const { return m_arraySizeAndFlags >> s_flagCount; }

    void setHasNameAttribute(bool hasName) const { updateFlag(s_flagHasNameAttribute, hasName); }

    bool styleAttributeIsDirty() const { return m_arraySizeAndFlags & s_flagStyleAttributeIsDirty; }
    void setStyleAttributeIsDirty(bool isDirty) const { updateFlag(s_flagStyleAttributeIsDirty, isDirty); }

    bool presentationalHintStyleIsDirty() const { return m_arraySizeAndFlags & s_flagPresentationalHintStyleIsDirty; }
    void setPresentationalHintStyleIsDirty(bool isDirty) const { updateFlag(s_flagPresentationalHintStyleIsDirty, isDirty); }

    bool animatedSVGAttributesAreDirty() const { return m_arraySizeAndFlags & s_flagAnimatedSVGAttributesAreDirty; }
    void setAnimatedSVGAttributesAreDirty(bool dirty) const { updateFlag(s_flagAnimatedSVGAttributesAreDirty, dirty); }

    mutable RefPtr<StyleProperties> m_inlineStyle;
    mutable SpaceSplitString m_classNames;
    mutable AtomString m_idForStyleResolution;

private:
    friend class Element;
    friend class StyledElement;
    friend class ShareableElementData;
    friend class UniqueElementData;
    friend class SVGElement;
    friend class HTMLImageElement;

    void destroy();

    const Attribute* attributeBase() const;
    const Attribute* findAttributeByName(const AtomString& name, bool shouldIgnoreAttributeCase) const;

    Ref<UniqueElementData> makeUniqueCopy() const;
};

#if COMPILER(MSVC)
#pragma warning(push)
#pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning
#endif

DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(ShareableElementData);
class ShareableElementData : public ElementData {
    WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(ShareableElementData);
public:
    static Ref<ShareableElementData> createWithAttributes(const Vector<Attribute>&);

    explicit ShareableElementData(const Vector<Attribute>&);
    explicit ShareableElementData(const UniqueElementData&);
    ~ShareableElementData();

    static ptrdiff_t attributeArrayMemoryOffset() { return OBJECT_OFFSETOF(ShareableElementData, m_attributeArray); }

    Attribute m_attributeArray[0];
};

#if COMPILER(MSVC)
#pragma warning(pop)
#endif

class UniqueElementData : public ElementData {
public:
    static Ref<UniqueElementData> create();
    Ref<ShareableElementData> makeShareableCopy() const;

    // These functions do no error/duplicate checking.
    void addAttribute(const QualifiedName&, const AtomString&);
    void removeAttribute(unsigned index);

    Attribute& attributeAt(unsigned index);
    Attribute* findAttributeByName(const QualifiedName&);

    UniqueElementData();
    explicit UniqueElementData(const ShareableElementData&);
    explicit UniqueElementData(const UniqueElementData&);

    static ptrdiff_t attributeVectorMemoryOffset() { return OBJECT_OFFSETOF(UniqueElementData, m_attributeVector); }

    mutable RefPtr<StyleProperties> m_presentationalHintStyle;
    typedef Vector<Attribute, 4> AttributeVector;
    AttributeVector m_attributeVector;
};

inline void ElementData::deref()
{
    if (!derefBase())
        return;
    destroy();
}

inline unsigned ElementData::length() const
{
    if (is<UniqueElementData>(*this))
        return downcast<UniqueElementData>(*this).m_attributeVector.size();
    return arraySize();
}

inline const Attribute* ElementData::attributeBase() const
{
    if (is<UniqueElementData>(*this))
        return downcast<UniqueElementData>(*this).m_attributeVector.data();
    return downcast<ShareableElementData>(*this).m_attributeArray;
}

inline const StyleProperties* ElementData::presentationalHintStyle() const
{
    if (!is<UniqueElementData>(*this))
        return nullptr;
    return downcast<UniqueElementData>(*this).m_presentationalHintStyle.get();
}

inline AttributeIteratorAccessor ElementData::attributesIterator() const
{
    if (is<UniqueElementData>(*this)) {
        const Vector<Attribute, 4>& attributeVector = downcast<UniqueElementData>(*this).m_attributeVector;
        return AttributeIteratorAccessor(attributeVector.data(), attributeVector.size());
    }
    return AttributeIteratorAccessor(downcast<ShareableElementData>(*this).m_attributeArray, arraySize());
}

ALWAYS_INLINE const Attribute* ElementData::findAttributeByName(const AtomString& name, bool shouldIgnoreAttributeCase) const
{
    unsigned index = findAttributeIndexByName(name, shouldIgnoreAttributeCase);
    if (index != attributeNotFound)
        return &attributeAt(index);
    return nullptr;
}

ALWAYS_INLINE unsigned ElementData::findAttributeIndexByName(const QualifiedName& name) const
{
    const Attribute* attributes = attributeBase();
    for (unsigned i = 0, count = length(); i < count; ++i) {
        if (attributes[i].name().matches(name))
            return i;
    }
    return attributeNotFound;
}

// We use a boolean parameter instead of calling shouldIgnoreAttributeCase so that the caller
// can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not).
ALWAYS_INLINE unsigned ElementData::findAttributeIndexByName(const AtomString& name, bool shouldIgnoreAttributeCase) const
{
    unsigned attributeCount = length();
    if (!attributeCount)
        return attributeNotFound;

    const Attribute* attributes = attributeBase();
    const AtomString& caseAdjustedName = shouldIgnoreAttributeCase ? name.convertToASCIILowercase() : name;

    unsigned attributeIndex = 0;
    do {
        const Attribute& attribute = attributes[attributeIndex];
        if (!attribute.name().hasPrefix()) {
            if (attribute.localName() == caseAdjustedName)
                return attributeIndex;
        } else {
            if (attribute.name().toString() == caseAdjustedName)
                return attributeIndex;
        }

        ++attributeIndex;
    } while (attributeIndex < attributeCount);

    return attributeNotFound;
}

ALWAYS_INLINE const Attribute* ElementData::findAttributeByName(const QualifiedName& name) const
{
    const Attribute* attributes = attributeBase();
    for (unsigned i = 0, count = length(); i < count; ++i) {
        if (attributes[i].name().matches(name))
            return &attributes[i];
    }
    return 0;
}

inline const Attribute& ElementData::attributeAt(unsigned index) const
{
    RELEASE_ASSERT(index < length());
    return attributeBase()[index];
}

inline void UniqueElementData::addAttribute(const QualifiedName& attributeName, const AtomString& value)
{
    m_attributeVector.append(Attribute(attributeName, value));
}

inline void UniqueElementData::removeAttribute(unsigned index)
{
    m_attributeVector.remove(index);
}

inline Attribute& UniqueElementData::attributeAt(unsigned index)
{
    return m_attributeVector.at(index);
}

} // namespace WebCore

SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ShareableElementData)
    static bool isType(const WebCore::ElementData& elementData) { return !elementData.isUnique(); }
SPECIALIZE_TYPE_TRAITS_END()

SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::UniqueElementData)
    static bool isType(const WebCore::ElementData& elementData) { return elementData.isUnique(); }
SPECIALIZE_TYPE_TRAITS_END()
