/*
 * Copyright (C) 2015 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 "ResourceValues.h"
#include "ValueVisitor.h"
#include "link/TableMerger.h"
#include "util/Util.h"

#include <cassert>

namespace aapt {

TableMerger::TableMerger(IAaptContext* context, ResourceTable* outTable,
                         const TableMergerOptions& options) :
        mContext(context), mMasterTable(outTable), mOptions(options) {
    // Create the desired package that all tables will be merged into.
    mMasterPackage = mMasterTable->createPackage(
            mContext->getCompilationPackage(), mContext->getPackageId());
    assert(mMasterPackage && "package name or ID already taken");
}

/**
 * This will merge packages with the same package name (or no package name).
 */
bool TableMerger::mergeImpl(const Source& src, ResourceTable* table,
                            bool overlay, bool allowNew) {
    const uint8_t desiredPackageId = mContext->getPackageId();

    bool error = false;
    for (auto& package : table->packages) {
        // Warn of packages with an unrelated ID.
        if (package->id && package->id.value() != 0x0 && package->id.value() != desiredPackageId) {
            mContext->getDiagnostics()->warn(DiagMessage(src)
                                             << "ignoring package " << package->name);
            continue;
        }

        if (package->name.empty() || mContext->getCompilationPackage() == package->name) {
            // Merge here. Once the entries are merged and mangled, any references to
            // them are still valid. This is because un-mangled references are
            // mangled, then looked up at resolution time.
            // Also, when linking, we convert references with no package name to use
            // the compilation package name.
            error |= !doMerge(src, table, package.get(),
                              false /* mangle */, overlay, allowNew, {});
        }
    }
    return !error;
}

bool TableMerger::merge(const Source& src, ResourceTable* table) {
    return mergeImpl(src, table, false /* overlay */, true /* allow new */);
}

bool TableMerger::mergeOverlay(const Source& src, ResourceTable* table) {
    return mergeImpl(src, table, true /* overlay */, mOptions.autoAddOverlay);
}

/**
 * This will merge and mangle resources from a static library.
 */
bool TableMerger::mergeAndMangle(const Source& src, const StringPiece16& packageName,
                                 ResourceTable* table, io::IFileCollection* collection) {
    bool error = false;
    for (auto& package : table->packages) {
        // Warn of packages with an unrelated ID.
        if (packageName != package->name) {
            mContext->getDiagnostics()->warn(DiagMessage(src)
                                             << "ignoring package " << package->name);
            continue;
        }

        bool mangle = packageName != mContext->getCompilationPackage();
        mMergedPackages.insert(package->name);

        auto callback = [&](const ResourceNameRef& name, const ConfigDescription& config,
                            FileReference* newFile, FileReference* oldFile) -> bool {
            // The old file's path points inside the APK, so we can use it as is.
            io::IFile* f = collection->findFile(util::utf16ToUtf8(*oldFile->path));
            if (!f) {
                mContext->getDiagnostics()->error(DiagMessage(src) << "file '" << *oldFile->path
                                                  << "' not found");
                return false;
            }

            mFilesToMerge[ResourceKeyRef(name, config)] = FileToMerge{
                    f, oldFile->getSource(), util::utf16ToUtf8(*newFile->path) };
            return true;
        };

        error |= !doMerge(src, table, package.get(),
                          mangle, false /* overlay */, true /* allow new */, callback);
    }
    return !error;
}

bool TableMerger::doMerge(const Source& src,
                          ResourceTable* srcTable,
                          ResourceTablePackage* srcPackage,
                          const bool manglePackage,
                          const bool overlay,
                          const bool allowNewResources,
                          FileMergeCallback callback) {
    bool error = false;

    for (auto& srcType : srcPackage->types) {
        ResourceTableType* dstType = mMasterPackage->findOrCreateType(srcType->type);
        if (srcType->symbolStatus.state == SymbolState::kPublic) {
            if (dstType->symbolStatus.state == SymbolState::kPublic && dstType->id && srcType->id
                    && dstType->id.value() == srcType->id.value()) {
                // Both types are public and have different IDs.
                mContext->getDiagnostics()->error(DiagMessage(src)
                                                  << "can not merge type '"
                                                  << srcType->type
                                                  << "': conflicting public IDs");
                error = true;
                continue;
            }

            dstType->symbolStatus = std::move(srcType->symbolStatus);
            dstType->id = srcType->id;
        }

        for (auto& srcEntry : srcType->entries) {
            ResourceEntry* dstEntry;
            if (manglePackage) {
                std::u16string mangledName = NameMangler::mangleEntry(srcPackage->name,
                                                                      srcEntry->name);
                if (allowNewResources) {
                    dstEntry = dstType->findOrCreateEntry(mangledName);
                } else {
                    dstEntry = dstType->findEntry(mangledName);
                }
            } else {
                if (allowNewResources) {
                    dstEntry = dstType->findOrCreateEntry(srcEntry->name);
                } else {
                    dstEntry = dstType->findEntry(srcEntry->name);
                }
            }

            if (!dstEntry) {
                mContext->getDiagnostics()->error(DiagMessage(src)
                                                  << "resource "
                                                  << ResourceNameRef(srcPackage->name,
                                                                     srcType->type,
                                                                     srcEntry->name)
                                                  << " does not override an existing resource");
                mContext->getDiagnostics()->note(DiagMessage(src)
                                                 << "define an <add-resource> tag or use "
                                                    "--auto-add-overlay");
                error = true;
                continue;
            }

            if (srcEntry->symbolStatus.state != SymbolState::kUndefined) {
                if (srcEntry->symbolStatus.state == SymbolState::kPublic) {
                    if (dstEntry->symbolStatus.state == SymbolState::kPublic &&
                            dstEntry->id && srcEntry->id &&
                            dstEntry->id.value() != srcEntry->id.value()) {
                        // Both entries are public and have different IDs.
                        mContext->getDiagnostics()->error(DiagMessage(src)
                                                          << "can not merge entry '"
                                                          << srcEntry->name
                                                          << "': conflicting public IDs");
                        error = true;
                        continue;
                    }

                    if (srcEntry->id) {
                        dstEntry->id = srcEntry->id;
                    }
                }

                if (dstEntry->symbolStatus.state != SymbolState::kPublic &&
                        dstEntry->symbolStatus.state != srcEntry->symbolStatus.state) {
                    dstEntry->symbolStatus = std::move(srcEntry->symbolStatus);
                }
            }

            ResourceNameRef resName(mMasterPackage->name, dstType->type, dstEntry->name);

            for (auto& srcValue : srcEntry->values) {
                ResourceConfigValue* dstValue = dstEntry->findValue(srcValue->config,
                                                                    srcValue->product);

                const bool stripConfig = mOptions.filter ?
                        !mOptions.filter->match(srcValue->config) : false;

                if (dstValue) {
                    const int collisionResult = ResourceTable::resolveValueCollision(
                            dstValue->value.get(), srcValue->value.get());
                    if (collisionResult == 0 && !overlay) {
                        // Error!
                        ResourceNameRef resourceName(srcPackage->name,
                                                     srcType->type,
                                                     srcEntry->name);

                        mContext->getDiagnostics()->error(DiagMessage(srcValue->value->getSource())
                                                          << "resource '" << resourceName
                                                          << "' has a conflicting value for "
                                                          << "configuration ("
                                                          << srcValue->config << ")");
                        mContext->getDiagnostics()->note(DiagMessage(dstValue->value->getSource())
                                                         << "originally defined here");
                        error = true;
                        continue;
                    } else if (collisionResult < 0) {
                        // Keep our existing value.
                        continue;
                    }

                }

                if (stripConfig) {
                    continue;
                }

                if (!dstValue) {
                    // Force create the entry if we didn't have it.
                    dstValue = dstEntry->findOrCreateValue(srcValue->config, srcValue->product);
                }

                if (FileReference* f = valueCast<FileReference>(srcValue->value.get())) {
                    std::unique_ptr<FileReference> newFileRef;
                    if (manglePackage) {
                        newFileRef = cloneAndMangleFile(srcPackage->name, *f);
                    } else {
                        newFileRef = std::unique_ptr<FileReference>(f->clone(
                                &mMasterTable->stringPool));
                    }

                    if (callback) {
                        if (!callback(resName, srcValue->config, newFileRef.get(), f)) {
                            error = true;
                            continue;
                        }
                    }
                    dstValue->value = std::move(newFileRef);

                } else {
                    dstValue->value = std::unique_ptr<Value>(srcValue->value->clone(
                            &mMasterTable->stringPool));
                }
            }
        }
    }
    return !error;
}

std::unique_ptr<FileReference> TableMerger::cloneAndMangleFile(const std::u16string& package,
                                                               const FileReference& fileRef) {

    StringPiece16 prefix, entry, suffix;
    if (util::extractResFilePathParts(*fileRef.path, &prefix, &entry, &suffix)) {
        std::u16string mangledEntry = NameMangler::mangleEntry(package, entry.toString());
        std::u16string newPath = prefix.toString() + mangledEntry + suffix.toString();
        std::unique_ptr<FileReference> newFileRef = util::make_unique<FileReference>(
                mMasterTable->stringPool.makeRef(newPath));
        newFileRef->setComment(fileRef.getComment());
        newFileRef->setSource(fileRef.getSource());
        return newFileRef;
    }
    return std::unique_ptr<FileReference>(fileRef.clone(&mMasterTable->stringPool));
}

bool TableMerger::mergeFileImpl(const ResourceFile& fileDesc, io::IFile* file, bool overlay) {
    ResourceTable table;
    std::u16string path = util::utf8ToUtf16(ResourceUtils::buildResourceFileName(fileDesc,
                                                                                 nullptr));
    std::unique_ptr<FileReference> fileRef = util::make_unique<FileReference>(
            table.stringPool.makeRef(path));
    fileRef->setSource(fileDesc.source);

    ResourceTablePackage* pkg = table.createPackage(fileDesc.name.package, 0x0);
    pkg->findOrCreateType(fileDesc.name.type)
            ->findOrCreateEntry(fileDesc.name.entry)
            ->findOrCreateValue(fileDesc.config, {})
            ->value = std::move(fileRef);

    auto callback = [&](const ResourceNameRef& name, const ConfigDescription& config,
                       FileReference* newFile, FileReference* oldFile) -> bool {
        mFilesToMerge[ResourceKeyRef(name, config)] = FileToMerge{
                file, oldFile->getSource(), util::utf16ToUtf8(*newFile->path) };
        return true;
    };

    return doMerge(file->getSource(), &table, pkg,
                   false /* mangle */, overlay /* overlay */, true /* allow new */, callback);
}

bool TableMerger::mergeFile(const ResourceFile& fileDesc, io::IFile* file) {
    return mergeFileImpl(fileDesc, file, false /* overlay */);
}

bool TableMerger::mergeFileOverlay(const ResourceFile& fileDesc, io::IFile* file) {
    return mergeFileImpl(fileDesc, file, true /* overlay */);
}

} // namespace aapt
