/*
 * 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 "AppInfo.h"
#include "BigBuffer.h"
#include "BinaryResourceParser.h"
#include "BindingXmlPullParser.h"
#include "Debug.h"
#include "Files.h"
#include "Flag.h"
#include "JavaClassGenerator.h"
#include "Linker.h"
#include "ManifestMerger.h"
#include "ManifestParser.h"
#include "ManifestValidator.h"
#include "NameMangler.h"
#include "Png.h"
#include "ResourceParser.h"
#include "ResourceTable.h"
#include "ResourceTableResolver.h"
#include "ResourceValues.h"
#include "SdkConstants.h"
#include "SourceXmlPullParser.h"
#include "StringPiece.h"
#include "TableFlattener.h"
#include "Util.h"
#include "XmlFlattener.h"
#include "ZipFile.h"

#include <algorithm>
#include <androidfw/AssetManager.h>
#include <cstdlib>
#include <dirent.h>
#include <errno.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <sys/stat.h>
#include <unordered_set>
#include <utils/Errors.h>

constexpr const char* kAaptVersionStr = "2.0-alpha";

using namespace aapt;

/**
 * Used with smart pointers to free malloc'ed memory.
 */
struct DeleteMalloc {
    void operator()(void* ptr) {
        free(ptr);
    }
};

struct StaticLibraryData {
    Source source;
    std::unique_ptr<ZipFile> apk;
};

/**
 * Collect files from 'root', filtering out any files that do not
 * match the FileFilter 'filter'.
 */
bool walkTree(const Source& root, const FileFilter& filter,
              std::vector<Source>* outEntries) {
    bool error = false;

    for (const std::string& dirName : listFiles(root.path)) {
        std::string dir = root.path;
        appendPath(&dir, dirName);

        FileType ft = getFileType(dir);
        if (!filter(dirName, ft)) {
            continue;
        }

        if (ft != FileType::kDirectory) {
            continue;
        }

        for (const std::string& fileName : listFiles(dir)) {
            std::string file(dir);
            appendPath(&file, fileName);

            FileType ft = getFileType(file);
            if (!filter(fileName, ft)) {
                continue;
            }

            if (ft != FileType::kRegular) {
                Logger::error(Source{ file }) << "not a regular file." << std::endl;
                error = true;
                continue;
            }
            outEntries->push_back(Source{ file });
        }
    }
    return !error;
}

void versionStylesForCompat(const std::shared_ptr<ResourceTable>& table) {
    for (auto& type : *table) {
        if (type->type != ResourceType::kStyle) {
            continue;
        }

        for (auto& entry : type->entries) {
            // Add the versioned styles we want to create
            // here. They are added to the table after
            // iterating over the original set of styles.
            //
            // A stack is used since auto-generated styles
            // from later versions should override
            // auto-generated styles from earlier versions.
            // Iterating over the styles is done in order,
            // so we will always visit sdkVersions from smallest
            // to largest.
            std::stack<ResourceConfigValue> addStack;

            for (ResourceConfigValue& configValue : entry->values) {
                visitFunc<Style>(*configValue.value, [&](Style& style) {
                    // Collect which entries we've stripped and the smallest
                    // SDK level which was stripped.
                    size_t minSdkStripped = std::numeric_limits<size_t>::max();
                    std::vector<Style::Entry> stripped;

                    // Iterate over the style's entries and erase/record the
                    // attributes whose SDK level exceeds the config's sdkVersion.
                    auto iter = style.entries.begin();
                    while (iter != style.entries.end()) {
                        if (iter->key.name.package == u"android") {
                            size_t sdkLevel = findAttributeSdkLevel(iter->key.name);
                            if (sdkLevel > 1 && sdkLevel > configValue.config.sdkVersion) {
                                // Record that we are about to strip this.
                                stripped.emplace_back(std::move(*iter));
                                minSdkStripped = std::min(minSdkStripped, sdkLevel);

                                // Erase this from this style.
                                iter = style.entries.erase(iter);
                                continue;
                            }
                        }
                        ++iter;
                    }

                    if (!stripped.empty()) {
                        // We have stripped attributes, so let's create a new style to hold them.
                        ConfigDescription versionConfig(configValue.config);
                        versionConfig.sdkVersion = minSdkStripped;

                        ResourceConfigValue value = {
                                versionConfig,
                                configValue.source,
                                {},

                                // Create a copy of the original style.
                                std::unique_ptr<Value>(configValue.value->clone(
                                            &table->getValueStringPool()))
                        };

                        Style& newStyle = static_cast<Style&>(*value.value);

                        // Move the recorded stripped attributes into this new style.
                        std::move(stripped.begin(), stripped.end(),
                                  std::back_inserter(newStyle.entries));

                        // We will add this style to the table later. If we do it now, we will
                        // mess up iteration.
                        addStack.push(std::move(value));
                    }
                });
            }

            auto comparator =
                    [](const ResourceConfigValue& lhs, const ConfigDescription& rhs) -> bool {
                        return lhs.config < rhs;
                    };

            while (!addStack.empty()) {
                ResourceConfigValue& value = addStack.top();
                auto iter = std::lower_bound(entry->values.begin(), entry->values.end(),
                                             value.config, comparator);
                if (iter == entry->values.end() || iter->config != value.config) {
                    entry->values.insert(iter, std::move(value));
                }
                addStack.pop();
            }
        }
    }
}

struct CompileItem {
    ResourceName name;
    ConfigDescription config;
    Source source;
    std::string extension;
};

struct LinkItem {
    ResourceName name;
    ConfigDescription config;
    Source source;
    std::string originalPath;
    ZipFile* apk;
    std::u16string originalPackage;
};

template <typename TChar>
static BasicStringPiece<TChar> getExtension(const BasicStringPiece<TChar>& str) {
    auto iter = std::find(str.begin(), str.end(), static_cast<TChar>('.'));
    if (iter == str.end()) {
        return BasicStringPiece<TChar>();
    }
    size_t offset = (iter - str.begin()) + 1;
    return str.substr(offset, str.size() - offset);
}

std::string buildFileReference(const ResourceNameRef& name, const ConfigDescription& config,
                               const StringPiece& extension) {
    std::stringstream path;
    path << "res/" << name.type;
    if (config != ConfigDescription{}) {
        path << "-" << config;
    }
    path << "/" << util::utf16ToUtf8(name.entry);
    if (!extension.empty()) {
        path << "." << extension;
    }
    return path.str();
}

std::string buildFileReference(const CompileItem& item) {
    return buildFileReference(item.name, item.config, item.extension);
}

std::string buildFileReference(const LinkItem& item) {
    return buildFileReference(item.name, item.config, getExtension<char>(item.originalPath));
}

template <typename T>
bool addFileReference(const std::shared_ptr<ResourceTable>& table, const T& item) {
    StringPool& pool = table->getValueStringPool();
    StringPool::Ref ref = pool.makeRef(util::utf8ToUtf16(buildFileReference(item)),
                                       StringPool::Context{ 0, item.config });
    return table->addResource(item.name, item.config, item.source.line(0),
                              util::make_unique<FileReference>(ref));
}

struct AaptOptions {
    enum class Phase {
        Link,
        Compile,
        Dump,
        DumpStyleGraph,
    };

    enum class PackageType {
        StandardApp,
        StaticLibrary,
    };

    // The phase to process.
    Phase phase;

    // The type of package to produce.
    PackageType packageType = PackageType::StandardApp;

    // Details about the app.
    AppInfo appInfo;

    // The location of the manifest file.
    Source manifest;

    // The APK files to link.
    std::vector<Source> input;

    // The libraries these files may reference.
    std::vector<Source> libraries;

    // Output path. This can be a directory or file
    // depending on the phase.
    Source output;

    // Directory in which to write binding xml files.
    Source bindingOutput;

    // Directory to in which to generate R.java.
    Maybe<Source> generateJavaClass;

    // Whether to output verbose details about
    // compilation.
    bool verbose = false;

    // Whether or not to auto-version styles or layouts
    // referencing attributes defined in a newer SDK
    // level than the style or layout is defined for.
    bool versionStylesAndLayouts = true;

    // The target style that will have it's style hierarchy dumped
    // when the phase is DumpStyleGraph.
    ResourceName dumpStyleTarget;
};

struct IdCollector : public xml::Visitor {
    IdCollector(const Source& source, const std::shared_ptr<ResourceTable>& table) :
            mSource(source), mTable(table) {
    }

    virtual void visit(xml::Text* node) override {}

    virtual void visit(xml::Namespace* node) override {
        for (const auto& child : node->children) {
            child->accept(this);
        }
    }

    virtual void visit(xml::Element* node) override {
        for (const xml::Attribute& attr : node->attributes) {
            bool create = false;
            bool priv = false;
            ResourceNameRef nameRef;
            if (ResourceParser::tryParseReference(attr.value, &nameRef, &create, &priv)) {
                if (create) {
                    mTable->addResource(nameRef, {}, mSource.line(node->lineNumber),
                                        util::make_unique<Id>());
                }
            }
        }

        for (const auto& child : node->children) {
            child->accept(this);
        }
    }

private:
    Source mSource;
    std::shared_ptr<ResourceTable> mTable;
};

bool compileXml(const AaptOptions& options, const std::shared_ptr<ResourceTable>& table,
                const CompileItem& item, ZipFile* outApk) {
    std::ifstream in(item.source.path, std::ifstream::binary);
    if (!in) {
        Logger::error(item.source) << strerror(errno) << std::endl;
        return false;
    }

    SourceLogger logger(item.source);
    std::unique_ptr<xml::Node> root = xml::inflate(&in, &logger);
    if (!root) {
        return false;
    }

    // Collect any resource ID's declared here.
    IdCollector idCollector(item.source, table);
    root->accept(&idCollector);

    BigBuffer outBuffer(1024);
    if (!xml::flatten(root.get(), options.appInfo.package, &outBuffer)) {
        logger.error() << "failed to encode XML." << std::endl;
        return false;
    }

    // Write the resulting compiled XML file to the output APK.
    if (outApk->add(outBuffer, buildFileReference(item).data(), ZipEntry::kCompressStored,
                nullptr) != android::NO_ERROR) {
        Logger::error(options.output) << "failed to write compiled '" << item.source
                                      << "' to apk." << std::endl;
        return false;
    }
    return true;
}

/**
 * Determines if a layout should be auto generated based on SDK level. We do not
 * generate a layout if there is already a layout defined whose SDK version is greater than
 * the one we want to generate.
 */
bool shouldGenerateVersionedResource(const std::shared_ptr<const ResourceTable>& table,
                                     const ResourceName& name, const ConfigDescription& config,
                                     int sdkVersionToGenerate) {
    assert(sdkVersionToGenerate > config.sdkVersion);
    const ResourceTableType* type;
    const ResourceEntry* entry;
    std::tie(type, entry) = table->findResource(name);
    assert(type && entry);

    auto iter = std::lower_bound(entry->values.begin(), entry->values.end(), config,
            [](const ResourceConfigValue& lhs, const ConfigDescription& config) -> bool {
        return lhs.config < config;
    });

    assert(iter != entry->values.end());
    ++iter;

    if (iter == entry->values.end()) {
        return true;
    }

    ConfigDescription newConfig = config;
    newConfig.sdkVersion = sdkVersionToGenerate;
    return newConfig < iter->config;
}

bool linkXml(const AaptOptions& options, const std::shared_ptr<ResourceTable>& table,
             const std::shared_ptr<IResolver>& resolver, const LinkItem& item,
             const void* data, size_t dataLen, ZipFile* outApk, std::queue<LinkItem>* outQueue) {
    SourceLogger logger(item.source);
    std::unique_ptr<xml::Node> root = xml::inflate(data, dataLen, &logger);
    if (!root) {
        return false;
    }

    xml::FlattenOptions xmlOptions;
    if (options.packageType == AaptOptions::PackageType::StaticLibrary) {
        xmlOptions.keepRawValues = true;
    }

    if (options.versionStylesAndLayouts) {
        // We strip attributes that do not belong in this version of the resource.
        // Non-version qualified resources have an implicit version 1 requirement.
        xmlOptions.maxSdkAttribute = item.config.sdkVersion ? item.config.sdkVersion : 1;
    }

    BigBuffer outBuffer(1024);
    Maybe<size_t> minStrippedSdk = xml::flattenAndLink(item.source, root.get(),
                                                       item.originalPackage, resolver,
                                                       xmlOptions, &outBuffer);
    if (!minStrippedSdk) {
        logger.error() << "failed to encode XML." << std::endl;
        return false;
    }

    if (minStrippedSdk.value() > 0) {
        // Something was stripped, so let's generate a new file
        // with the version of the smallest SDK version stripped.
        // We can only generate a versioned layout if there doesn't exist a layout
        // with sdk version greater than the current one but less than the one we
        // want to generate.
        if (shouldGenerateVersionedResource(table, item.name, item.config,
                    minStrippedSdk.value())) {
            LinkItem newWork = item;
            newWork.config.sdkVersion = minStrippedSdk.value();
            outQueue->push(newWork);

            if (!addFileReference(table, newWork)) {
                Logger::error(options.output) << "failed to add auto-versioned resource '"
                                              << newWork.name << "'." << std::endl;
                return false;
            }
        }
    }

    if (outApk->add(outBuffer, buildFileReference(item).data(), ZipEntry::kCompressDeflated,
                nullptr) != android::NO_ERROR) {
        Logger::error(options.output) << "failed to write linked file '"
                                      << buildFileReference(item) << "' to apk." << std::endl;
        return false;
    }
    return true;
}

bool compilePng(const AaptOptions& options, const CompileItem& item, ZipFile* outApk) {
    std::ifstream in(item.source.path, std::ifstream::binary);
    if (!in) {
        Logger::error(item.source) << strerror(errno) << std::endl;
        return false;
    }

    BigBuffer outBuffer(4096);
    std::string err;
    Png png;
    if (!png.process(item.source, in, &outBuffer, {}, &err)) {
        Logger::error(item.source) << err << std::endl;
        return false;
    }

    if (outApk->add(outBuffer, buildFileReference(item).data(), ZipEntry::kCompressStored,
                nullptr) != android::NO_ERROR) {
        Logger::error(options.output) << "failed to write compiled '" << item.source
                                      << "' to apk." << std::endl;
        return false;
    }
    return true;
}

bool copyFile(const AaptOptions& options, const CompileItem& item, ZipFile* outApk) {
    if (outApk->add(item.source.path.data(), buildFileReference(item).data(),
                ZipEntry::kCompressStored, nullptr) != android::NO_ERROR) {
        Logger::error(options.output) << "failed to copy file '" << item.source << "' to apk."
                                      << std::endl;
        return false;
    }
    return true;
}

bool compileManifest(const AaptOptions& options, const std::shared_ptr<IResolver>& resolver,
                     const std::map<std::shared_ptr<ResourceTable>, StaticLibraryData>& libApks,
                     const android::ResTable& table, ZipFile* outApk) {
    if (options.verbose) {
        Logger::note(options.manifest) << "compiling AndroidManifest.xml." << std::endl;
    }

    std::ifstream in(options.manifest.path, std::ifstream::binary);
    if (!in) {
        Logger::error(options.manifest) << strerror(errno) << std::endl;
        return false;
    }

    SourceLogger logger(options.manifest);
    std::unique_ptr<xml::Node> root = xml::inflate(&in, &logger);
    if (!root) {
        return false;
    }

    ManifestMerger merger({});
    if (!merger.setAppManifest(options.manifest, options.appInfo.package, std::move(root))) {
        return false;
    }

    for (const auto& entry : libApks) {
        ZipFile* libApk = entry.second.apk.get();
        const std::u16string& libPackage = entry.first->getPackage();
        const Source& libSource = entry.second.source;

        ZipEntry* zipEntry = libApk->getEntryByName("AndroidManifest.xml");
        if (!zipEntry) {
            continue;
        }

        std::unique_ptr<void, DeleteMalloc> uncompressedData = std::unique_ptr<void, DeleteMalloc>(
                libApk->uncompress(zipEntry));
        assert(uncompressedData);

        SourceLogger logger(libSource);
        std::unique_ptr<xml::Node> libRoot = xml::inflate(uncompressedData.get(),
                                                          zipEntry->getUncompressedLen(), &logger);
        if (!libRoot) {
            return false;
        }

        if (!merger.mergeLibraryManifest(libSource, libPackage, std::move(libRoot))) {
            return false;
        }
    }

    BigBuffer outBuffer(1024);
    if (!xml::flattenAndLink(options.manifest, merger.getMergedXml(), options.appInfo.package,
                resolver, {}, &outBuffer)) {
        return false;
    }

    std::unique_ptr<uint8_t[]> data = util::copy(outBuffer);

    android::ResXMLTree tree;
    if (tree.setTo(data.get(), outBuffer.size(), false) != android::NO_ERROR) {
        return false;
    }

    ManifestValidator validator(table);
    if (!validator.validate(options.manifest, &tree)) {
        return false;
    }

    if (outApk->add(data.get(), outBuffer.size(), "AndroidManifest.xml",
                ZipEntry::kCompressStored, nullptr) != android::NO_ERROR) {
        Logger::error(options.output) << "failed to write 'AndroidManifest.xml' to apk."
                                      << std::endl;
        return false;
    }
    return true;
}

static bool compileValues(const std::shared_ptr<ResourceTable>& table, const Source& source,
                          const ConfigDescription& config) {
    std::ifstream in(source.path, std::ifstream::binary);
    if (!in) {
        Logger::error(source) << strerror(errno) << std::endl;
        return false;
    }

    std::shared_ptr<XmlPullParser> xmlParser = std::make_shared<SourceXmlPullParser>(in);
    ResourceParser parser(table, source, config, xmlParser);
    return parser.parse();
}

struct ResourcePathData {
    std::u16string resourceDir;
    std::u16string name;
    std::string extension;
    ConfigDescription config;
};

/**
 * Resource file paths are expected to look like:
 * [--/res/]type[-config]/name
 */
static Maybe<ResourcePathData> extractResourcePathData(const Source& source) {
    // TODO(adamlesinski): Use Windows path separator on windows.
    std::vector<std::string> parts = util::splitAndLowercase(source.path, '/');
    if (parts.size() < 2) {
        Logger::error(source) << "bad resource path." << std::endl;
        return {};
    }

    std::string& dir = parts[parts.size() - 2];
    StringPiece dirStr = dir;

    ConfigDescription config;
    size_t dashPos = dir.find('-');
    if (dashPos != std::string::npos) {
        StringPiece configStr = dirStr.substr(dashPos + 1, dir.size() - (dashPos + 1));
        if (!ConfigDescription::parse(configStr, &config)) {
            Logger::error(source)
                    << "invalid configuration '"
                    << configStr
                    << "'."
                    << std::endl;
            return {};
        }
        dirStr = dirStr.substr(0, dashPos);
    }

    std::string& filename = parts[parts.size() - 1];
    StringPiece name = filename;
    StringPiece extension;
    size_t dotPos = filename.find('.');
    if (dotPos != std::string::npos) {
        extension = name.substr(dotPos + 1, filename.size() - (dotPos + 1));
        name = name.substr(0, dotPos);
    }

    return ResourcePathData{
            util::utf8ToUtf16(dirStr),
            util::utf8ToUtf16(name),
            extension.toString(),
            config
    };
}

bool writeResourceTable(const AaptOptions& options, const std::shared_ptr<ResourceTable>& table,
                        const TableFlattener::Options& flattenerOptions, ZipFile* outApk) {
    if (table->begin() != table->end()) {
        BigBuffer buffer(1024);
        TableFlattener flattener(flattenerOptions);
        if (!flattener.flatten(&buffer, *table)) {
            Logger::error() << "failed to flatten resource table." << std::endl;
            return false;
        }

        if (options.verbose) {
            Logger::note() << "Final resource table size=" << util::formatSize(buffer.size())
                           << std::endl;
        }

        if (outApk->add(buffer, "resources.arsc", ZipEntry::kCompressStored, nullptr) !=
                android::NO_ERROR) {
            Logger::note(options.output) << "failed to store resource table." << std::endl;
            return false;
        }
    }
    return true;
}

/**
 * For each FileReference in the table, adds a LinkItem to the link queue for processing.
 */
static void addApkFilesToLinkQueue(const std::u16string& package, const Source& source,
                                   const std::shared_ptr<ResourceTable>& table,
                                   const std::unique_ptr<ZipFile>& apk,
                                   std::queue<LinkItem>* outLinkQueue) {
    bool mangle = package != table->getPackage();
    for (auto& type : *table) {
        for (auto& entry : type->entries) {
            ResourceName name = { package, type->type, entry->name };
            if (mangle) {
                NameMangler::mangle(table->getPackage(), &name.entry);
            }

            for (auto& value : entry->values) {
                visitFunc<FileReference>(*value.value, [&](FileReference& ref) {
                    std::string pathUtf8 = util::utf16ToUtf8(*ref.path);
                    Source newSource = source;
                    newSource.path += "/";
                    newSource.path += pathUtf8;
                    outLinkQueue->push(LinkItem{
                            name, value.config, newSource, pathUtf8, apk.get(),
                            table->getPackage() });
                    // Now rewrite the file path.
                    if (mangle) {
                        ref.path = table->getValueStringPool().makeRef(util::utf8ToUtf16(
                                    buildFileReference(name, value.config,
                                                       getExtension<char>(pathUtf8))));
                    }
                });
            }
        }
    }
}

static constexpr int kOpenFlags = ZipFile::kOpenCreate | ZipFile::kOpenTruncate |
        ZipFile::kOpenReadWrite;

bool link(const AaptOptions& options, const std::shared_ptr<ResourceTable>& outTable,
          const std::shared_ptr<IResolver>& resolver) {
    std::map<std::shared_ptr<ResourceTable>, StaticLibraryData> apkFiles;
    std::unordered_set<std::u16string> linkedPackages;

    // Populate the linkedPackages with our own.
    linkedPackages.insert(options.appInfo.package);

    // Load all APK files.
    for (const Source& source : options.input) {
        std::unique_ptr<ZipFile> zipFile = util::make_unique<ZipFile>();
        if (zipFile->open(source.path.data(), ZipFile::kOpenReadOnly) != android::NO_ERROR) {
            Logger::error(source) << "failed to open: " << strerror(errno) << std::endl;
            return false;
        }

        std::shared_ptr<ResourceTable> table = std::make_shared<ResourceTable>();

        ZipEntry* entry = zipFile->getEntryByName("resources.arsc");
        if (!entry) {
            Logger::error(source) << "missing 'resources.arsc'." << std::endl;
            return false;
        }

        std::unique_ptr<void, DeleteMalloc> uncompressedData = std::unique_ptr<void, DeleteMalloc>(
                zipFile->uncompress(entry));
        assert(uncompressedData);

        BinaryResourceParser parser(table, resolver, source, uncompressedData.get(),
                                    entry->getUncompressedLen());
        if (!parser.parse()) {
            return false;
        }

        // Keep track of where this table came from.
        apkFiles[table] = StaticLibraryData{ source, std::move(zipFile) };

        // Add the package to the set of linked packages.
        linkedPackages.insert(table->getPackage());
    }

    std::queue<LinkItem> linkQueue;
    for (auto& p : apkFiles) {
        const std::shared_ptr<ResourceTable>& inTable = p.first;

        // Collect all FileReferences and add them to the queue for processing.
        addApkFilesToLinkQueue(options.appInfo.package, p.second.source, inTable, p.second.apk,
                               &linkQueue);

        // Merge the tables.
        if (!outTable->merge(std::move(*inTable))) {
            return false;
        }
    }

    // Version all styles referencing attributes outside of their specified SDK version.
    if (options.versionStylesAndLayouts) {
        versionStylesForCompat(outTable);
    }

    {
        // Now that everything is merged, let's link it.
        Linker::Options linkerOptions;
        if (options.packageType == AaptOptions::PackageType::StaticLibrary) {
            linkerOptions.linkResourceIds = false;
        }
        Linker linker(outTable, resolver, linkerOptions);
        if (!linker.linkAndValidate()) {
            return false;
        }

        // Verify that all symbols exist.
        const auto& unresolvedRefs = linker.getUnresolvedReferences();
        if (!unresolvedRefs.empty()) {
            for (const auto& entry : unresolvedRefs) {
                for (const auto& source : entry.second) {
                    Logger::error(source) << "unresolved symbol '" << entry.first << "'."
                                          << std::endl;
                }
            }
            return false;
        }
    }

    // Open the output APK file for writing.
    ZipFile outApk;
    if (outApk.open(options.output.path.data(), kOpenFlags) != android::NO_ERROR) {
        Logger::error(options.output) << "failed to open: " << strerror(errno) << std::endl;
        return false;
    }

    android::ResTable binTable;
    if (!compileManifest(options, resolver, apkFiles, binTable, &outApk)) {
        return false;
    }

    for (; !linkQueue.empty(); linkQueue.pop()) {
        const LinkItem& item = linkQueue.front();

        assert(!item.originalPackage.empty());
        ZipEntry* entry = item.apk->getEntryByName(item.originalPath.data());
        if (!entry) {
            Logger::error(item.source) << "failed to find '" << item.originalPath << "'."
                                       << std::endl;
            return false;
        }

        if (util::stringEndsWith<char>(item.originalPath, ".xml")) {
            void* uncompressedData = item.apk->uncompress(entry);
            assert(uncompressedData);

            if (!linkXml(options, outTable, resolver, item, uncompressedData,
                        entry->getUncompressedLen(), &outApk, &linkQueue)) {
                Logger::error(options.output) << "failed to link '" << item.originalPath << "'."
                                              << std::endl;
                return false;
            }
        } else {
            if (outApk.add(item.apk, entry, buildFileReference(item).data(), 0, nullptr) !=
                    android::NO_ERROR) {
                Logger::error(options.output) << "failed to copy '" << item.originalPath << "'."
                                              << std::endl;
                return false;
            }
        }
    }

    // Generate the Java class file.
    if (options.generateJavaClass) {
        JavaClassGenerator::Options javaOptions;
        if (options.packageType == AaptOptions::PackageType::StaticLibrary) {
            javaOptions.useFinal = false;
        }
        JavaClassGenerator generator(outTable, javaOptions);

        for (const std::u16string& package : linkedPackages) {
            Source outPath = options.generateJavaClass.value();

            // Build the output directory from the package name.
            // Eg. com.android.app -> com/android/app
            const std::string packageUtf8 = util::utf16ToUtf8(package);
            for (StringPiece part : util::tokenize<char>(packageUtf8, '.')) {
                appendPath(&outPath.path, part);
            }

            if (!mkdirs(outPath.path)) {
                Logger::error(outPath) << strerror(errno) << std::endl;
                return false;
            }

            appendPath(&outPath.path, "R.java");

            if (options.verbose) {
                Logger::note(outPath) << "writing Java symbols." << std::endl;
            }

            std::ofstream fout(outPath.path);
            if (!fout) {
                Logger::error(outPath) << strerror(errno) << std::endl;
                return false;
            }

            if (!generator.generate(package, fout)) {
                Logger::error(outPath) << generator.getError() << "." << std::endl;
                return false;
            }
        }
    }

    outTable->getValueStringPool().prune();
    outTable->getValueStringPool().sort(
            [](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
                if (a.context.priority < b.context.priority) {
                    return true;
                }

                if (a.context.priority > b.context.priority) {
                    return false;
                }
                return a.value < b.value;
            });


    // Flatten the resource table.
    TableFlattener::Options flattenerOptions;
    if (options.packageType != AaptOptions::PackageType::StaticLibrary) {
        flattenerOptions.useExtendedChunks = false;
    }

    if (!writeResourceTable(options, outTable, flattenerOptions, &outApk)) {
        return false;
    }

    outApk.flush();
    return true;
}

bool compile(const AaptOptions& options, const std::shared_ptr<ResourceTable>& table,
             const std::shared_ptr<IResolver>& resolver) {
    std::queue<CompileItem> compileQueue;
    bool error = false;

    // Compile all the resource files passed in on the command line.
    for (const Source& source : options.input) {
        // Need to parse the resource type/config/filename.
        Maybe<ResourcePathData> maybePathData = extractResourcePathData(source);
        if (!maybePathData) {
            return false;
        }

        const ResourcePathData& pathData = maybePathData.value();
        if (pathData.resourceDir == u"values") {
            // The file is in the values directory, which means its contents will
            // go into the resource table.
            if (options.verbose) {
                Logger::note(source) << "compiling values." << std::endl;
            }

            error |= !compileValues(table, source, pathData.config);
        } else {
            // The file is in a directory like 'layout' or 'drawable'. Find out
            // the type.
            const ResourceType* type = parseResourceType(pathData.resourceDir);
            if (!type) {
                Logger::error(source) << "invalid resource type '" << pathData.resourceDir << "'."
                                      << std::endl;
                return false;
            }

            compileQueue.push(CompileItem{
                    ResourceName{ table->getPackage(), *type, pathData.name },
                    pathData.config,
                    source,
                    pathData.extension
            });
        }
    }

    if (error) {
        return false;
    }
    // Open the output APK file for writing.
    ZipFile outApk;
    if (outApk.open(options.output.path.data(), kOpenFlags) != android::NO_ERROR) {
        Logger::error(options.output) << "failed to open: " << strerror(errno) << std::endl;
        return false;
    }

    // Compile each file.
    for (; !compileQueue.empty(); compileQueue.pop()) {
        const CompileItem& item = compileQueue.front();

        // Add the file name to the resource table.
        error |= !addFileReference(table, item);

        if (item.extension == "xml") {
            error |= !compileXml(options, table, item, &outApk);
        } else if (item.extension == "png" || item.extension == "9.png") {
            error |= !compilePng(options, item, &outApk);
        } else {
            error |= !copyFile(options, item, &outApk);
        }
    }

    if (error) {
        return false;
    }

    // Link and assign resource IDs.
    Linker linker(table, resolver, {});
    if (!linker.linkAndValidate()) {
        return false;
    }

    // Flatten the resource table.
    if (!writeResourceTable(options, table, {}, &outApk)) {
        return false;
    }

    outApk.flush();
    return true;
}

bool loadAppInfo(const Source& source, AppInfo* outInfo) {
    std::ifstream ifs(source.path, std::ifstream::in | std::ifstream::binary);
    if (!ifs) {
        Logger::error(source) << strerror(errno) << std::endl;
        return false;
    }

    ManifestParser parser;
    std::shared_ptr<XmlPullParser> pullParser = std::make_shared<SourceXmlPullParser>(ifs);
    return parser.parse(source, pullParser, outInfo);
}

static void printCommandsAndDie() {
    std::cerr << "The following commands are supported:" << std::endl << std::endl;
    std::cerr << "compile       compiles a subset of resources" << std::endl;
    std::cerr << "link          links together compiled resources and libraries" << std::endl;
    std::cerr << "dump          dumps resource contents to to standard out" << std::endl;
    std::cerr << std::endl;
    std::cerr << "run aapt2 with one of the commands and the -h flag for extra details."
              << std::endl;
    exit(1);
}

static AaptOptions prepareArgs(int argc, char** argv) {
    if (argc < 2) {
        std::cerr << "no command specified." << std::endl << std::endl;
        printCommandsAndDie();
    }

    const StringPiece command(argv[1]);
    argc -= 2;
    argv += 2;

    AaptOptions options;

    if (command == "--version" || command == "version") {
        std::cout << kAaptVersionStr << std::endl;
        exit(0);
    } else if (command == "link") {
        options.phase = AaptOptions::Phase::Link;
    } else if (command == "compile") {
        options.phase = AaptOptions::Phase::Compile;
    } else if (command == "dump") {
        options.phase = AaptOptions::Phase::Dump;
    } else if (command == "dump-style-graph") {
        options.phase = AaptOptions::Phase::DumpStyleGraph;
    } else {
        std::cerr << "invalid command '" << command << "'." << std::endl << std::endl;
        printCommandsAndDie();
    }

    bool isStaticLib = false;
    if (options.phase == AaptOptions::Phase::Compile ||
            options.phase == AaptOptions::Phase::Link) {
        if (options.phase == AaptOptions::Phase::Compile) {
            flag::requiredFlag("--package", "Android package name",
                    [&options](const StringPiece& arg) {
                        options.appInfo.package = util::utf8ToUtf16(arg);
                    });
        } else if (options.phase == AaptOptions::Phase::Link) {
            flag::requiredFlag("--manifest", "AndroidManifest.xml of your app",
                    [&options](const StringPiece& arg) {
                        options.manifest = Source{ arg.toString() };
                    });

            flag::optionalFlag("-I", "add an Android APK to link against",
                    [&options](const StringPiece& arg) {
                        options.libraries.push_back(Source{ arg.toString() });
                    });

            flag::optionalFlag("--java", "directory in which to generate R.java",
                    [&options](const StringPiece& arg) {
                        options.generateJavaClass = Source{ arg.toString() };
                    });

            flag::optionalSwitch("--static-lib", "generate a static Android library", true,
                                 &isStaticLib);

            flag::optionalFlag("--binding", "Output directory for binding XML files",
                    [&options](const StringPiece& arg) {
                        options.bindingOutput = Source{ arg.toString() };
                    });
            flag::optionalSwitch("--no-version", "Disables automatic style and layout versioning",
                                 false, &options.versionStylesAndLayouts);
        }

        // Common flags for all steps.
        flag::requiredFlag("-o", "Output path", [&options](const StringPiece& arg) {
            options.output = Source{ arg.toString() };
        });
    } else if (options.phase == AaptOptions::Phase::DumpStyleGraph) {
        flag::requiredFlag("--style", "Name of the style to dump",
                [&options](const StringPiece& arg, std::string* outError) -> bool {
                    Reference styleReference;
                    if (!ResourceParser::parseStyleParentReference(util::utf8ToUtf16(arg),
                                &styleReference, outError)) {
                        return false;
                    }
                    options.dumpStyleTarget = styleReference.name;
                    return true;
                });
    }

    bool help = false;
    flag::optionalSwitch("-v", "enables verbose logging", true, &options.verbose);
    flag::optionalSwitch("-h", "displays this help menu", true, &help);

    // Build the command string for output (eg. "aapt2 compile").
    std::string fullCommand = "aapt2";
    fullCommand += " ";
    fullCommand += command.toString();

    // Actually read the command line flags.
    flag::parse(argc, argv, fullCommand);

    if (help) {
        flag::usageAndDie(fullCommand);
    }

    if (isStaticLib) {
        options.packageType = AaptOptions::PackageType::StaticLibrary;
    }

    // Copy all the remaining arguments.
    for (const std::string& arg : flag::getArgs()) {
        options.input.push_back(Source{ arg });
    }
    return options;
}

static bool doDump(const AaptOptions& options) {
    for (const Source& source : options.input) {
        std::unique_ptr<ZipFile> zipFile = util::make_unique<ZipFile>();
        if (zipFile->open(source.path.data(), ZipFile::kOpenReadOnly) != android::NO_ERROR) {
            Logger::error(source) << "failed to open: " << strerror(errno) << std::endl;
            return false;
        }

        std::shared_ptr<ResourceTable> table = std::make_shared<ResourceTable>();
        std::shared_ptr<ResourceTableResolver> resolver =
                std::make_shared<ResourceTableResolver>(
                        table, std::vector<std::shared_ptr<const android::AssetManager>>());

        ZipEntry* entry = zipFile->getEntryByName("resources.arsc");
        if (!entry) {
            Logger::error(source) << "missing 'resources.arsc'." << std::endl;
            return false;
        }

        std::unique_ptr<void, DeleteMalloc> uncompressedData = std::unique_ptr<void, DeleteMalloc>(
                zipFile->uncompress(entry));
        assert(uncompressedData);

        BinaryResourceParser parser(table, resolver, source, uncompressedData.get(),
                                    entry->getUncompressedLen());
        if (!parser.parse()) {
            return false;
        }

        if (options.phase == AaptOptions::Phase::Dump) {
            Debug::printTable(table);
        } else if (options.phase == AaptOptions::Phase::DumpStyleGraph) {
            Debug::printStyleGraph(table, options.dumpStyleTarget);
        }
    }
    return true;
}

int main(int argc, char** argv) {
    Logger::setLog(std::make_shared<Log>(std::cerr, std::cerr));
    AaptOptions options = prepareArgs(argc, argv);

    if (options.phase == AaptOptions::Phase::Dump ||
            options.phase == AaptOptions::Phase::DumpStyleGraph) {
        if (!doDump(options)) {
            return 1;
        }
        return 0;
    }

    // If we specified a manifest, go ahead and load the package name from the manifest.
    if (!options.manifest.path.empty()) {
        if (!loadAppInfo(options.manifest, &options.appInfo)) {
            return false;
        }
    }

    // Verify we have some common options set.
    if (options.appInfo.package.empty()) {
        Logger::error() << "no package name specified." << std::endl;
        return false;
    }

    // Every phase needs a resource table.
    std::shared_ptr<ResourceTable> table = std::make_shared<ResourceTable>();
    table->setPackage(options.appInfo.package);
    if (options.appInfo.package == u"android") {
        table->setPackageId(0x01);
    } else {
        table->setPackageId(0x7f);
    }

    // Load the included libraries.
    std::vector<std::shared_ptr<const android::AssetManager>> sources;
    for (const Source& source : options.libraries) {
        std::shared_ptr<android::AssetManager> assetManager =
                std::make_shared<android::AssetManager>();
        int32_t cookie;
        if (!assetManager->addAssetPath(android::String8(source.path.data()), &cookie)) {
            Logger::error(source) << "failed to load library." << std::endl;
            return false;
        }

        if (cookie == 0) {
            Logger::error(source) << "failed to load library." << std::endl;
            return false;
        }
        sources.push_back(assetManager);
    }

    // Make the resolver that will cache IDs for us.
    std::shared_ptr<ResourceTableResolver> resolver = std::make_shared<ResourceTableResolver>(
            table, sources);

    if (options.phase == AaptOptions::Phase::Compile) {
        if (!compile(options, table, resolver)) {
            Logger::error() << "aapt exiting with failures." << std::endl;
            return 1;
        }
    } else if (options.phase == AaptOptions::Phase::Link) {
        if (!link(options, table, resolver)) {
            Logger::error() << "aapt exiting with failures." << std::endl;
            return 1;
        }
    }
    return 0;
}
