//
// Copyright 2006 The Android Open Source Project
//
// Build resource files from raw assets.
//

#ifndef XML_NODE_H
#define XML_NODE_H

#include "StringPool.h"
#include "ResourceTable.h"

class XMLNode;

extern const char* const RESOURCES_ROOT_NAMESPACE;
extern const char* const RESOURCES_ANDROID_NAMESPACE;

bool isWhitespace(const char16_t* str);

String16 getNamespaceResourcePackage(String16 namespaceUri, bool* outIsPublic = NULL);

status_t parseStyledString(Bundle* bundle,
                           const char* fileName,
                           ResXMLTree* inXml,
                           const String16& endTag,
                           String16* outString,
                           Vector<StringPool::entry_style_span>* outSpans,
                           bool isFormatted,
                           PseudolocalizationMethod isPseudolocalizable);

void printXMLBlock(ResXMLTree* block);

status_t parseXMLResource(const sp<AaptFile>& file, ResXMLTree* outTree,
                          bool stripAll=true, bool keepComments=false,
                          const char** cDataTags=NULL);

class XMLNode : public RefBase
{
public:
    static sp<XMLNode> parse(const sp<AaptFile>& file);

    static inline
    sp<XMLNode> newNamespace(const String8& filename, const String16& prefix, const String16& uri) {
        return new XMLNode(filename, prefix, uri, true);
    }
    
    static inline
    sp<XMLNode> newElement(const String8& filename, const String16& ns, const String16& name) {
        return new XMLNode(filename, ns, name, false);
    }
    
    static inline
    sp<XMLNode> newCData(const String8& filename) {
        return new XMLNode(filename);
    }
    
    enum type {
        TYPE_NAMESPACE,
        TYPE_ELEMENT,
        TYPE_CDATA
    };
    
    type getType() const;
    
    const String16& getNamespacePrefix() const;
    const String16& getNamespaceUri() const;
    
    const String16& getElementNamespace() const;
    const String16& getElementName() const;
    const Vector<sp<XMLNode> >& getChildren() const;

    const String8& getFilename() const;
    
    struct attribute_entry {
        attribute_entry() : index(~(uint32_t)0), nameResId(0)
        {
            value.dataType = Res_value::TYPE_NULL;
        }

        bool needStringValue() const {
            return nameResId == 0
                || value.dataType == Res_value::TYPE_NULL
                || value.dataType == Res_value::TYPE_STRING;
        }
        
        String16 ns;
        String16 name;
        String16 string;
        Res_value value;
        uint32_t index;
        uint32_t nameResId;
        mutable uint32_t namePoolIdx;
    };

    const Vector<attribute_entry>& getAttributes() const;

    const attribute_entry* getAttribute(const String16& ns, const String16& name) const;
    
    attribute_entry* editAttribute(const String16& ns, const String16& name);

    const String16& getCData() const;

    const String16& getComment() const;

    int32_t getStartLineNumber() const;
    int32_t getEndLineNumber() const;

    sp<XMLNode> searchElement(const String16& tagNamespace, const String16& tagName);
    
    sp<XMLNode> getChildElement(const String16& tagNamespace, const String16& tagName);
    
    status_t addChild(const sp<XMLNode>& child);

    status_t insertChildAt(const sp<XMLNode>& child, size_t index);

    status_t addAttribute(const String16& ns, const String16& name,
                          const String16& value);

    void setAttributeResID(size_t attrIdx, uint32_t resId);

    status_t appendChars(const String16& chars);

    status_t appendComment(const String16& comment);

    void setStartLineNumber(int32_t line);
    void setEndLineNumber(int32_t line);

    void removeWhitespace(bool stripAll=true, const char** cDataTags=NULL);

    void setUTF8(bool val) { mUTF8 = val; }

    status_t parseValues(const sp<AaptAssets>& assets, ResourceTable* table);

    status_t assignResourceIds(const sp<AaptAssets>& assets,
                               const ResourceTable* table = NULL);

    status_t flatten(const sp<AaptFile>& dest, bool stripComments,
            bool stripRawValues) const;

    void print(int indent=0);

private:
    struct ParseState
    {
        String8 filename;
        XML_Parser parser;
        sp<XMLNode> root;
        Vector<sp<XMLNode> > stack;
        String16 pendingComment;
    };

    static void XMLCALL
    startNamespace(void *userData, const char *prefix, const char *uri);
    static void XMLCALL
    startElement(void *userData, const char *name, const char **atts);
    static void XMLCALL
    characterData(void *userData, const XML_Char *s, int len);
    static void XMLCALL
    endElement(void *userData, const char *name);
    static void XMLCALL
    endNamespace(void *userData, const char *prefix);
    
    static void XMLCALL
    commentData(void *userData, const char *comment);
    
    // Creating an element node.
    XMLNode(const String8& filename, const String16& s1, const String16& s2, bool isNamespace);
    
    // Creating a CDATA node.
    XMLNode(const String8& filename);
    
    status_t collect_strings(StringPool* dest, Vector<uint32_t>* outResIds,
            bool stripComments, bool stripRawValues) const;

    status_t collect_attr_strings(StringPool* outPool,
        Vector<uint32_t>* outResIds, bool allAttrs) const;
        
    status_t collect_resid_strings(StringPool* outPool,
            Vector<uint32_t>* outResIds) const;

    status_t flatten_node(const StringPool& strings, const sp<AaptFile>& dest,
            bool stripComments, bool stripRawValues) const;

    String16 mNamespacePrefix;
    String16 mNamespaceUri;
    String16 mElementName;
    Vector<sp<XMLNode> > mChildren;
    Vector<attribute_entry> mAttributes;
    KeyedVector<uint32_t, uint32_t> mAttributeOrder;
    uint32_t mNextAttributeIndex;
    String16 mChars;
    Res_value mCharsValue;
    String16 mComment;
    String8 mFilename;
    int32_t mStartLineNumber;
    int32_t mEndLineNumber;

    // Encode compiled XML with UTF-8 StringPools?
    bool mUTF8;
};

#endif
