/*
   Copyright (C) 2008 Apple, Inc

   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 SVGGlyphMap_h
#define SVGGlyphMap_h

#if ENABLE(SVG_FONTS)
#include "SVGGlyphElement.h"

namespace WTF
{
struct QCharHash {
    static unsigned hash(const QChar &c)
    {
        return c.unicode();
    }
    static bool equal(const QChar &a, const QChar &b)
    {
        return a == b;
    }
    static const bool safeToCompareToEmptyOrDeleted = false;
};
template<> struct HashTraits<QChar> : public GenericHashTraits<QChar> {
    static const bool emptyValueIsZero = true;
    static const bool needsDestruction = false;
    static const bool needsRef = false;
    static QChar deletedValue()
    {
        return QChar(-1);
    }
    static bool isDeletedValue(const QChar &)
    {
        return false;
    }
    static QChar constructDeletedValue(QChar *)
    {
        return QChar(-1);
    }
};
template<> struct DefaultHash<QChar> {
    typedef QCharHash Hash;
};
}

namespace WebCore
{

struct GlyphMapNode;

typedef HashMap<UChar, RefPtr<GlyphMapNode> > GlyphMapLayer;

struct GlyphMapNode : public RefCounted<GlyphMapNode> {
private:
    GlyphMapNode() { }
public:
    static PassRefPtr<GlyphMapNode> create()
    {
        return adoptRef(new GlyphMapNode);
    }

    Vector<SVGGlyphIdentifier> glyphs;

    GlyphMapLayer children;
};

class SVGGlyphMap
{

public:
    SVGGlyphMap() : m_currentPriority(0) { }

    void add(const String &string, const SVGGlyphIdentifier &glyph)
    {
        size_t len = string.length();
        GlyphMapLayer *currentLayer = &m_rootLayer;

        RefPtr<GlyphMapNode> node;
        for (size_t i = 0; i < len; i++) {
            UChar curChar = string[i];
            node = currentLayer->get(curChar);
            if (!node) {
                node = GlyphMapNode::create();
                currentLayer->set(curChar, node);
            }
            currentLayer = &node->children;
        }

        if (node) {
            node->glyphs.append(glyph);
            node->glyphs.last().priority = m_currentPriority++;
            node->glyphs.last().nameLength = len;
            node->glyphs.last().isValid = true;
        }
    }

    static inline bool compareGlyphPriority(const SVGGlyphIdentifier &first, const SVGGlyphIdentifier &second)
    {
        return first.priority < second.priority;
    }

    void get(const String &string, Vector<SVGGlyphIdentifier> &glyphs)
    {
        GlyphMapLayer *currentLayer = &m_rootLayer;

        for (size_t i = 0; i < string.length(); i++) {
            UChar curChar = string[i];
            RefPtr<GlyphMapNode> node = currentLayer->get(curChar);
            if (!node) {
                break;
            }
            glyphs.append(node->glyphs);
            currentLayer = &node->children;
        }
        std::sort(glyphs.begin(), glyphs.end(), compareGlyphPriority);
    }

    void clear()
    {
        m_rootLayer.clear();
        m_currentPriority = 0;
    }

private:
    GlyphMapLayer m_rootLayer;
    int m_currentPriority;
};

}

#endif // ENABLE(SVG_FONTS)

#endif //SVGGlyphMap_h
