/*
 * Copyright (C) 2016 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 "ResourceTable.h"
#include "ResourceUtils.h"
#include "ValueVisitor.h"
#include "proto/ProtoHelpers.h"
#include "proto/ProtoSerialize.h"

#include <androidfw/ResourceTypes.h>

namespace aapt {

namespace {

class ReferenceIdToNameVisitor : public ValueVisitor {
public:
    using ValueVisitor::visit;

    explicit ReferenceIdToNameVisitor(const std::map<ResourceId, ResourceNameRef>* mapping) :
            mMapping(mapping) {
        assert(mMapping);
    }

    void visit(Reference* reference) override {
        if (!reference->id || !reference->id.value().isValid()) {
            return;
        }

        ResourceId id = reference->id.value();
        auto cacheIter = mMapping->find(id);
        if (cacheIter != mMapping->end()) {
            reference->name = cacheIter->second.toResourceName();
        }
    }

private:
    const std::map<ResourceId, ResourceNameRef>* mMapping;
};

class PackagePbDeserializer {
public:
    PackagePbDeserializer(const android::ResStringPool* valuePool,
                          const android::ResStringPool* sourcePool,
                          const android::ResStringPool* symbolPool,
                          const Source& source, IDiagnostics* diag) :
            mValuePool(valuePool), mSourcePool(sourcePool), mSymbolPool(symbolPool),
            mSource(source), mDiag(diag) {
    }

public:
    bool deserializeFromPb(const pb::Package& pbPackage, ResourceTable* table) {
        Maybe<uint8_t> id;
        if (pbPackage.has_package_id()) {
            id = static_cast<uint8_t>(pbPackage.package_id());
        }

        std::map<ResourceId, ResourceNameRef> idIndex;

        ResourceTablePackage* pkg = table->createPackage(
                util::utf8ToUtf16(pbPackage.package_name()), id);
        for (const pb::Type& pbType : pbPackage.types()) {
            const ResourceType* resType = parseResourceType(util::utf8ToUtf16(pbType.name()));
            if (!resType) {
                mDiag->error(DiagMessage(mSource) << "unknown type '" << pbType.name() << "'");
                return {};
            }

            ResourceTableType* type = pkg->findOrCreateType(*resType);

            for (const pb::Entry& pbEntry : pbType.entries()) {
                ResourceEntry* entry = type->findOrCreateEntry(util::utf8ToUtf16(pbEntry.name()));

                // Deserialize the symbol status (public/private with source and comments).
                if (pbEntry.has_symbol_status()) {
                    const pb::SymbolStatus& pbStatus = pbEntry.symbol_status();
                    if (pbStatus.has_source()) {
                        deserializeSourceFromPb(pbStatus.source(), *mSourcePool,
                                                &entry->symbolStatus.source);
                    }

                    if (pbStatus.has_comment()) {
                        entry->symbolStatus.comment = util::utf8ToUtf16(pbStatus.comment());
                    }

                    SymbolState visibility = deserializeVisibilityFromPb(pbStatus.visibility());
                    entry->symbolStatus.state = visibility;

                    if (visibility == SymbolState::kPublic) {
                        // This is a public symbol, we must encode the ID now if there is one.
                        if (pbEntry.has_id()) {
                            entry->id = static_cast<uint16_t>(pbEntry.id());
                        }

                        if (type->symbolStatus.state != SymbolState::kPublic) {
                            // If the type has not been made public, do so now.
                            type->symbolStatus.state = SymbolState::kPublic;
                            if (pbType.has_id()) {
                                type->id = static_cast<uint8_t>(pbType.id());
                            }
                        }
                    } else if (visibility == SymbolState::kPrivate) {
                        if (type->symbolStatus.state == SymbolState::kUndefined) {
                            type->symbolStatus.state = SymbolState::kPrivate;
                        }
                    }
                }

                ResourceId resId(pbPackage.package_id(), pbType.id(), pbEntry.id());
                if (resId.isValid()) {
                    idIndex[resId] = ResourceNameRef(pkg->name, type->type, entry->name);
                }

                for (const pb::ConfigValue& pbConfigValue : pbEntry.config_values()) {
                    const pb::ConfigDescription& pbConfig = pbConfigValue.config();

                    ConfigDescription config;
                    if (!deserializeConfigDescriptionFromPb(pbConfig, &config)) {
                        mDiag->error(DiagMessage(mSource) << "invalid configuration");
                        return {};
                    }

                    ResourceConfigValue* configValue = entry->findOrCreateValue(config,
                                                                                pbConfig.product());
                    if (configValue->value) {
                        // Duplicate config.
                        mDiag->error(DiagMessage(mSource) << "duplicate configuration");
                        return {};
                    }

                    configValue->value = deserializeValueFromPb(pbConfigValue.value(),
                                                                config, &table->stringPool);
                    if (!configValue->value) {
                        return {};
                    }
                }
            }
        }

        ReferenceIdToNameVisitor visitor(&idIndex);
        visitAllValuesInPackage(pkg, &visitor);
        return true;
    }

private:
    std::unique_ptr<Item> deserializeItemFromPb(const pb::Item& pbItem,
                                                const ConfigDescription& config,
                                                StringPool* pool) {
        if (pbItem.has_ref()) {
            const pb::Reference& pbRef = pbItem.ref();
            std::unique_ptr<Reference> ref = util::make_unique<Reference>();
            if (!deserializeReferenceFromPb(pbRef, ref.get())) {
                return {};
            }
            return std::move(ref);

        } else if (pbItem.has_prim()) {
            const pb::Primitive& pbPrim = pbItem.prim();
            android::Res_value prim = {};
            prim.dataType = static_cast<uint8_t>(pbPrim.type());
            prim.data = pbPrim.data();
            return util::make_unique<BinaryPrimitive>(prim);

        } else if (pbItem.has_id()) {
            return util::make_unique<Id>();

        } else if (pbItem.has_str()) {
            const uint32_t idx = pbItem.str().idx();
            StringPiece16 str = util::getString(*mValuePool, idx);

            const android::ResStringPool_span* spans = mValuePool->styleAt(idx);
            if (spans && spans->name.index != android::ResStringPool_span::END) {
                StyleString styleStr = { str.toString() };
                while (spans->name.index != android::ResStringPool_span::END) {
                    styleStr.spans.push_back(Span{
                            util::getString(*mValuePool, spans->name.index).toString(),
                            spans->firstChar,
                            spans->lastChar
                    });
                    spans++;
                }
                return util::make_unique<StyledString>(
                        pool->makeRef(styleStr, StringPool::Context{ 1, config }));
            }
            return util::make_unique<String>(
                    pool->makeRef(str, StringPool::Context{ 1, config }));

        } else if (pbItem.has_raw_str()) {
            const uint32_t idx = pbItem.raw_str().idx();
            StringPiece16 str = util::getString(*mValuePool, idx);
            return util::make_unique<RawString>(
                    pool->makeRef(str, StringPool::Context{ 1, config }));

        } else if (pbItem.has_file()) {
            const uint32_t idx = pbItem.file().path_idx();
            StringPiece16 str = util::getString(*mValuePool, idx);
            return util::make_unique<FileReference>(
                    pool->makeRef(str, StringPool::Context{ 0, config }));

        } else {
            mDiag->error(DiagMessage(mSource) << "unknown item");
        }
        return {};
    }

    std::unique_ptr<Value> deserializeValueFromPb(const pb::Value& pbValue,
                                                  const ConfigDescription& config,
                                                  StringPool* pool) {
        const bool isWeak = pbValue.has_weak() ? pbValue.weak() : false;

        std::unique_ptr<Value> value;
        if (pbValue.has_item()) {
            value = deserializeItemFromPb(pbValue.item(), config, pool);
            if (!value) {
                return {};
            }

        } else if (pbValue.has_compound_value()) {
            const pb::CompoundValue pbCompoundValue = pbValue.compound_value();
            if (pbCompoundValue.has_attr()) {
                const pb::Attribute& pbAttr = pbCompoundValue.attr();
                std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(isWeak);
                attr->typeMask = pbAttr.format_flags();
                for (const pb::Attribute_Symbol& pbSymbol : pbAttr.symbols()) {
                    Attribute::Symbol symbol;
                    deserializeItemCommon(pbSymbol, &symbol.symbol);
                    if (!deserializeReferenceFromPb(pbSymbol.name(), &symbol.symbol)) {
                        return {};
                    }
                    symbol.value = pbSymbol.value();
                    attr->symbols.push_back(std::move(symbol));
                }
                value = std::move(attr);

            } else if (pbCompoundValue.has_style()) {
                const pb::Style& pbStyle = pbCompoundValue.style();
                std::unique_ptr<Style> style = util::make_unique<Style>();
                if (pbStyle.has_parent()) {
                    style->parent = Reference();
                    if (!deserializeReferenceFromPb(pbStyle.parent(), &style->parent.value())) {
                        return {};
                    }

                    if (pbStyle.has_parent_source()) {
                        Source parentSource;
                        deserializeSourceFromPb(pbStyle.parent_source(), *mSourcePool,
                                                &parentSource);
                        style->parent.value().setSource(std::move(parentSource));
                    }
                }

                for (const pb::Style_Entry& pbEntry : pbStyle.entries()) {
                    Style::Entry entry;
                    deserializeItemCommon(pbEntry, &entry.key);
                    if (!deserializeReferenceFromPb(pbEntry.key(), &entry.key)) {
                        return {};
                    }

                    entry.value = deserializeItemFromPb(pbEntry.item(), config, pool);
                    if (!entry.value) {
                        return {};
                    }

                    deserializeItemCommon(pbEntry, entry.value.get());
                    style->entries.push_back(std::move(entry));
                }
                value = std::move(style);

            } else if (pbCompoundValue.has_styleable()) {
                const pb::Styleable& pbStyleable = pbCompoundValue.styleable();
                std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
                for (const pb::Styleable_Entry& pbEntry : pbStyleable.entries()) {
                    Reference attrRef;
                    deserializeItemCommon(pbEntry, &attrRef);
                    deserializeReferenceFromPb(pbEntry.attr(), &attrRef);
                    styleable->entries.push_back(std::move(attrRef));
                }
                value = std::move(styleable);

            } else if (pbCompoundValue.has_array()) {
                const pb::Array& pbArray = pbCompoundValue.array();
                std::unique_ptr<Array> array = util::make_unique<Array>();
                for (const pb::Array_Entry& pbEntry : pbArray.entries()) {
                    std::unique_ptr<Item> item = deserializeItemFromPb(pbEntry.item(), config,
                                                                       pool);
                    if (!item) {
                        return {};
                    }

                    deserializeItemCommon(pbEntry, item.get());
                    array->items.push_back(std::move(item));
                }
                value = std::move(array);

            } else if (pbCompoundValue.has_plural()) {
                const pb::Plural& pbPlural = pbCompoundValue.plural();
                std::unique_ptr<Plural> plural = util::make_unique<Plural>();
                for (const pb::Plural_Entry& pbEntry : pbPlural.entries()) {
                    size_t pluralIdx = deserializePluralEnumFromPb(pbEntry.arity());
                    plural->values[pluralIdx] = deserializeItemFromPb(pbEntry.item(), config,
                                                                      pool);
                    if (!plural->values[pluralIdx]) {
                        return {};
                    }

                    deserializeItemCommon(pbEntry, plural->values[pluralIdx].get());
                }
                value = std::move(plural);

            } else {
                mDiag->error(DiagMessage(mSource) << "unknown compound value");
                return {};
            }
        } else {
            mDiag->error(DiagMessage(mSource) << "unknown value");
            return {};
        }

        assert(value && "forgot to set value");

        value->setWeak(isWeak);
        deserializeItemCommon(pbValue, value.get());
        return value;
    }

    bool deserializeReferenceFromPb(const pb::Reference& pbRef, Reference* outRef) {
        outRef->referenceType = deserializeReferenceTypeFromPb(pbRef.type());
        outRef->privateReference = pbRef.private_();

        if (!pbRef.has_id() && !pbRef.has_symbol_idx()) {
            return false;
        }

        if (pbRef.has_id()) {
            outRef->id = ResourceId(pbRef.id());
        }

        if (pbRef.has_symbol_idx()) {
            StringPiece16 strSymbol = util::getString(*mSymbolPool, pbRef.symbol_idx());
            ResourceNameRef nameRef;
            if (!ResourceUtils::parseResourceName(strSymbol, &nameRef, nullptr)) {
                mDiag->error(DiagMessage(mSource) << "invalid reference name '"
                             << strSymbol << "'");
                return false;
            }

            outRef->name = nameRef.toResourceName();
        }
        return true;
    }

    template <typename T>
    void deserializeItemCommon(const T& pbItem, Value* outValue) {
        if (pbItem.has_source()) {
            Source source;
            deserializeSourceFromPb(pbItem.source(), *mSourcePool, &source);
            outValue->setSource(std::move(source));
        }

        if (pbItem.has_comment()) {
            outValue->setComment(util::utf8ToUtf16(pbItem.comment()));
        }
    }

private:
    const android::ResStringPool* mValuePool;
    const android::ResStringPool* mSourcePool;
    const android::ResStringPool* mSymbolPool;
    const Source mSource;
    IDiagnostics* mDiag;
};

} // namespace

std::unique_ptr<ResourceTable> deserializeTableFromPb(const pb::ResourceTable& pbTable,
                                                      const Source& source,
                                                      IDiagnostics* diag) {
    // We import the android namespace because on Windows NO_ERROR is a macro, not an enum, which
    // causes errors when qualifying it with android::
    using namespace android;

    std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();

    if (!pbTable.has_string_pool()) {
        diag->error(DiagMessage(source) << "no string pool found");
        return {};
    }

    ResStringPool valuePool;
    status_t result = valuePool.setTo(pbTable.string_pool().data().data(),
                                      pbTable.string_pool().data().size());
    if (result != NO_ERROR) {
        diag->error(DiagMessage(source) << "invalid string pool");
        return {};
    }

    ResStringPool sourcePool;
    if (pbTable.has_source_pool()) {
        result = sourcePool.setTo(pbTable.source_pool().data().data(),
                                  pbTable.source_pool().data().size());
        if (result != NO_ERROR) {
            diag->error(DiagMessage(source) << "invalid source pool");
            return {};
        }
    }

    ResStringPool symbolPool;
    if (pbTable.has_symbol_pool()) {
        result = symbolPool.setTo(pbTable.symbol_pool().data().data(),
                                  pbTable.symbol_pool().data().size());
        if (result != NO_ERROR) {
            diag->error(DiagMessage(source) << "invalid symbol pool");
            return {};
        }
    }

    PackagePbDeserializer packagePbDeserializer(&valuePool, &sourcePool, &symbolPool, source, diag);
    for (const pb::Package& pbPackage : pbTable.packages()) {
        if (!packagePbDeserializer.deserializeFromPb(pbPackage, table.get())) {
            return {};
        }
    }
    return table;
}

std::unique_ptr<ResourceFile> deserializeCompiledFileFromPb(const pb::CompiledFile& pbFile,
                                                            const Source& source,
                                                            IDiagnostics* diag) {
    std::unique_ptr<ResourceFile> file = util::make_unique<ResourceFile>();

    ResourceNameRef nameRef;

    // Need to create an lvalue here so that nameRef can point to something real.
    std::u16string utf16Name = util::utf8ToUtf16(pbFile.resource_name());
    if (!ResourceUtils::parseResourceName(utf16Name, &nameRef)) {
        diag->error(DiagMessage(source) << "invalid resource name in compiled file header: "
                    << pbFile.resource_name());
        return {};
    }
    file->name = nameRef.toResourceName();
    file->source.path = pbFile.source_path();
    deserializeConfigDescriptionFromPb(pbFile.config(), &file->config);

    for (const pb::CompiledFile_Symbol& pbSymbol : pbFile.exported_symbols()) {
        // Need to create an lvalue here so that nameRef can point to something real.
        utf16Name = util::utf8ToUtf16(pbSymbol.resource_name());
        if (!ResourceUtils::parseResourceName(utf16Name, &nameRef)) {
            diag->error(DiagMessage(source) << "invalid resource name for exported symbol in "
                                               "compiled file header: "
                                            << pbFile.resource_name());
            return {};
        }
        file->exportedSymbols.push_back(
                SourcedResourceName{ nameRef.toResourceName(), pbSymbol.line_no() });
    }
    return file;
}

CompiledFileInputStream::CompiledFileInputStream(const void* data, size_t size) :
        mIn(static_cast<const uint8_t*>(data), size), mPbFile(),
        mData(static_cast<const uint8_t*>(data)), mSize(size) {
}

const pb::CompiledFile* CompiledFileInputStream::CompiledFile() {
    if (!mPbFile) {
        std::unique_ptr<pb::CompiledFile> pbFile = util::make_unique<pb::CompiledFile>();
        uint64_t pbSize = 0u;
        if (!mIn.ReadLittleEndian64(&pbSize)) {
            return nullptr;
        }
        mIn.PushLimit(static_cast<int>(pbSize));
        if (!pbFile->ParsePartialFromCodedStream(&mIn)) {
            return nullptr;
        }

        const size_t padding = 4 - (pbSize & 0x03);
        const size_t offset = sizeof(uint64_t) + pbSize + padding;
        if (offset > mSize) {
            return nullptr;
        }

        mData += offset;
        mSize -= offset;
        mPbFile = std::move(pbFile);
    }
    return mPbFile.get();
}

const void* CompiledFileInputStream::data() {
    if (!mPbFile) {
        if (!CompiledFile()) {
            return nullptr;
        }
    }
    return mData;
}

size_t CompiledFileInputStream::size() {
    if (!mPbFile) {
        if (!CompiledFile()) {
            return 0;
        }
    }
    return mSize;
}

} // namespace aapt
