/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <androidfw/ResourceTypes.h>
#include <utils/String8.h>

#include "AaptXml.h"

using namespace android;

namespace AaptXml {

static String8 getStringAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex,
        String8* outError) {
    Res_value value;
    if (tree.getAttributeValue(attrIndex, &value) < 0) {
        if (outError != NULL) {
            *outError = "could not find attribute at index";
        }
        return String8();
    }

    if (value.dataType != Res_value::TYPE_STRING) {
        if (outError != NULL) {
            *outError = "attribute is not a string value";
        }
        return String8();
    }

    size_t len;
    const char16_t* str = tree.getAttributeStringValue(attrIndex, &len);
    return str ? String8(str, len) : String8();
}

static int32_t getIntegerAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex,
    int32_t defValue, String8* outError) {
    Res_value value;
    if (tree.getAttributeValue(attrIndex, &value) < 0) {
        if (outError != NULL) {
            *outError = "could not find attribute at index";
        }
        return defValue;
    }

    if (value.dataType < Res_value::TYPE_FIRST_INT
            || value.dataType > Res_value::TYPE_LAST_INT) {
        if (outError != NULL) {
            *outError = "attribute is not an integer value";
        }
        return defValue;
    }
    return value.data;
}


ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes) {
    size_t attrCount = tree.getAttributeCount();
    for (size_t i = 0; i < attrCount; i++) {
        if (tree.getAttributeNameResID(i) == attrRes) {
            return (ssize_t)i;
        }
    }
    return -1;
}

String8 getAttribute(const ResXMLTree& tree, const char* ns,
        const char* attr, String8* outError) {
    ssize_t idx = tree.indexOfAttribute(ns, attr);
    if (idx < 0) {
        return String8();
    }
    return getStringAttributeAtIndex(tree, idx, outError);
}

String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError) {
    ssize_t idx = indexOfAttribute(tree, attrRes);
    if (idx < 0) {
        return String8();
    }
    return getStringAttributeAtIndex(tree, idx, outError);
}

String8 getResolvedAttribute(const ResTable& resTable, const ResXMLTree& tree,
        uint32_t attrRes, String8* outError) {
    ssize_t idx = indexOfAttribute(tree, attrRes);
    if (idx < 0) {
        return String8();
    }

    Res_value value;
    if (tree.getAttributeValue(idx, &value) == BAD_TYPE) {
        if (outError != NULL) {
            *outError = "attribute value is corrupt";
        }
        return String8();
    }

    // Check if the string is inline in the XML.
    if (value.dataType == Res_value::TYPE_STRING) {
        size_t len;
        const char16_t* str = tree.getAttributeStringValue(idx, &len);
        return str ? String8(str, len) : String8();
    }

    // Resolve the reference if there is one.
    ssize_t block = resTable.resolveReference(&value, 0);
    if (block < 0) {
        if (outError != NULL) {
            *outError = "attribute value reference does not exist";
        }
        return String8();
    }

    if (value.dataType != Res_value::TYPE_STRING) {
        if (outError != NULL) {
            *outError = "attribute is not a string value";
        }
        return String8();
    }

    size_t len;
    const char16_t* str = resTable.valueToString(&value, static_cast<size_t>(block), NULL, &len);
    return str ? String8(str, len) : String8();
}

int32_t getIntegerAttribute(const ResXMLTree& tree, const char* ns,
        const char* attr, int32_t defValue, String8* outError) {
    ssize_t idx = tree.indexOfAttribute(ns, attr);
    if (idx < 0) {
        return defValue;
    }
    return getIntegerAttributeAtIndex(tree, idx, defValue, outError);
}

int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, int32_t defValue,
        String8* outError) {
    ssize_t idx = indexOfAttribute(tree, attrRes);
    if (idx < 0) {
        return defValue;
    }
    return getIntegerAttributeAtIndex(tree, idx, defValue, outError);
}

int32_t getResolvedIntegerAttribute(const ResTable& resTable, const ResXMLTree& tree,
        uint32_t attrRes, int32_t defValue, String8* outError) {
    ssize_t idx = indexOfAttribute(tree, attrRes);
    if (idx < 0) {
        return defValue;
    }
    Res_value value;
    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
        if (value.dataType == Res_value::TYPE_REFERENCE) {
            resTable.resolveReference(&value, 0);
        }
        if (value.dataType < Res_value::TYPE_FIRST_INT
                || value.dataType > Res_value::TYPE_LAST_INT) {
            if (outError != NULL) {
                *outError = "attribute is not an integer value";
            }
            return defValue;
        }
    }
    return value.data;
}

void getResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree,
        uint32_t attrRes, Res_value* outValue, String8* outError) {
    ssize_t idx = indexOfAttribute(tree, attrRes);
    if (idx < 0) {
        if (outError != NULL) {
            *outError = "attribute could not be found";
        }
        return;
    }
    if (tree.getAttributeValue(idx, outValue) != NO_ERROR) {
        if (outValue->dataType == Res_value::TYPE_REFERENCE) {
            resTable.resolveReference(outValue, 0);
        }
        // The attribute was found and was resolved if need be.
        return;
    }
    if (outError != NULL) {
        *outError = "error getting resolved resource attribute";
    }
}

} // namespace AaptXml
