/*
 * Copyright (C) 2017 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 <getopt.h>
#include <sysexits.h>
#include <unistd.h>

#include <iostream>
#include <map>

#include <android-base/file.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <utils/Errors.h>
#include <vintf/KernelConfigParser.h>
#include <vintf/VintfObject.h>
#include <vintf/parse_string.h>
#include <vintf/parse_xml.h>
#include "utils.h"

namespace android {
namespace vintf {
namespace details {

// fake sysprops
using Properties = std::map<std::string, std::string>;

using Dirmap = std::map<std::string, std::string>;

enum Option : int {
    DUMP_FILE_LIST = 1,
    ROOTDIR,
    HELP,
    PROPERTY,
    CHECK_COMPAT,
    DIR_MAP,
    KERNEL,
};
// command line arguments
using Args = std::multimap<Option, std::string>;

class HostFileSystem : public details::FileSystemImpl {
   public:
    HostFileSystem(const Dirmap& dirmap) : mDirMap(dirmap) {}
    status_t fetch(const std::string& path, std::string* fetched,
                   std::string* error) const override {
        auto resolved = resolve(path);
        if (resolved.empty()) {
            std::cerr << "Error: Cannot resolve path " << path << std::endl;
            return UNKNOWN_ERROR;
        }
        status_t status = details::FileSystemImpl::fetch(resolved, fetched, error);
        std::cerr << "Debug: Fetch '" << resolved << "': " << toString(status) << std::endl;
        return status;
    }
    status_t listFiles(const std::string& path, std::vector<std::string>* out,
                       std::string* error) const override {
        auto resolved = resolve(path);
        if (resolved.empty()) {
            std::cerr << "Error: Cannot resolve path " << path << std::endl;
            return UNKNOWN_ERROR;
        }
        status_t status = details::FileSystemImpl::listFiles(resolved, out, error);
        std::cerr << "Debug: List '" << resolved << "': " << toString(status) << std::endl;
        return status;
    }

   private:
    static std::string toString(status_t status) {
        return status == OK ? "SUCCESS" : strerror(-status);
    }
    std::string resolve(const std::string& path) const {
        for (auto [prefix, mappedPath] : mDirMap) {
            if (path == prefix) {
                return mappedPath;
            }
            if (android::base::StartsWith(path, prefix + "/")) {
                return mappedPath + "/" + path.substr(prefix.size() + 1);
            }
        }
        return "";
    }

    Dirmap mDirMap;
};

class PresetPropertyFetcher : public PropertyFetcher {
   public:
    std::string getProperty(const std::string& key,
                            const std::string& defaultValue) const override {
        auto it = mProps.find(key);
        if (it == mProps.end()) {
            std::cerr << "Debug: Sysprop " << key << " is missing, default to '" << defaultValue
                      << "'" << std::endl;
            return defaultValue;
        }
        std::cerr << "Debug: Sysprop " << key << "=" << it->second << std::endl;
        return it->second;
    }
    uint64_t getUintProperty(const std::string& key, uint64_t defaultValue,
                             uint64_t max) const override {
        uint64_t result;
        std::string value = getProperty(key, "");
        if (!value.empty() && android::base::ParseUint(value, &result, max)) return result;
        return defaultValue;
    }
    bool getBoolProperty(const std::string& key, bool defaultValue) const override {
        std::string value = getProperty(key, "");
        if (value == "1" || value == "true") {
            return true;
        } else if (value == "0" || value == "false") {
            return false;
        }
        return defaultValue;
    }
    void setProperties(const Properties& props) { mProps.insert(props.begin(), props.end()); }

   private:
    std::map<std::string, std::string> mProps;
};

struct StaticRuntimeInfo : public RuntimeInfo {
    KernelVersion kernelVersion;
    std::string kernelConfigFile;

    status_t fetchAllInformation(FetchFlags flags) override {
        if (flags & RuntimeInfo::FetchFlag::CPU_VERSION) {
            mKernel.mVersion = kernelVersion;
            std::cerr << "Debug: fetched kernel version " << kernelVersion << std::endl;
        }
        if (flags & RuntimeInfo::FetchFlag::CONFIG_GZ) {
            std::string content;
            if (!android::base::ReadFileToString(kernelConfigFile, &content)) {
                std::cerr << "Error: Cannot read " << kernelConfigFile << std::endl;
                return UNKNOWN_ERROR;
            }
            KernelConfigParser parser;
            auto status = parser.processAndFinish(content);
            if (status != OK) {
                return status;
            }
            mKernel.mConfigs = std::move(parser.configs());
            std::cerr << "Debug: read kernel configs from " << kernelConfigFile << std::endl;
        }
        if (flags & RuntimeInfo::FetchFlag::POLICYVERS) {
            mKernelSepolicyVersion = SIZE_MAX;
        }
        return OK;
    }
};

struct StubRuntimeInfo : public RuntimeInfo {
    status_t fetchAllInformation(FetchFlags) override { return UNKNOWN_ERROR; }
};

struct StaticRuntimeInfoFactory : public ObjectFactory<RuntimeInfo> {
    std::shared_ptr<RuntimeInfo> info;
    StaticRuntimeInfoFactory(std::shared_ptr<RuntimeInfo> i) : info(i) {}
    std::shared_ptr<RuntimeInfo> make_shared() const override {
        if (info) return info;
        return std::make_shared<StubRuntimeInfo>();
    }
};

// helper functions
template <typename T>
std::unique_ptr<T> readObject(FileSystem* fileSystem, const std::string& path,
                              const XmlConverter<T>& converter) {
    std::string xml;
    std::string error;
    status_t err = fileSystem->fetch(path, &xml, &error);
    if (err != OK) {
        std::cerr << "Error: Cannot read '" << path << "' (" << strerror(-err) << "): " << error
                  << std::endl;
        return nullptr;
    }
    auto ret = std::make_unique<T>();
    if (!converter(ret.get(), xml, &error)) {
        std::cerr << "Error: Cannot parse '" << path << "': " << error << std::endl;
        return nullptr;
    }
    return ret;
}

int checkCompatibilityForFiles(const std::string& manifestPath, const std::string& matrixPath) {
    auto fileSystem = std::make_unique<FileSystemImpl>();
    auto manifest = readObject(fileSystem.get(), manifestPath, gHalManifestConverter);
    auto matrix = readObject(fileSystem.get(), matrixPath, gCompatibilityMatrixConverter);
    if (manifest == nullptr || matrix == nullptr) {
        return -1;
    }

    std::string error;
    if (!manifest->checkCompatibility(*matrix, &error)) {
        std::cerr << "Error: Incompatible: " << error << std::endl;
        std::cout << "false" << std::endl;
        return 1;
    }

    std::cout << "true" << std::endl;
    return 0;
}

Args parseArgs(int argc, char** argv) {
    int longOptFlag;
    int optionIndex;
    Args ret;
    std::vector<struct option> longopts{
        {"dump-file-list", no_argument, &longOptFlag, DUMP_FILE_LIST},
        {"rootdir", required_argument, &longOptFlag, ROOTDIR},
        {"help", no_argument, &longOptFlag, HELP},
        {"property", required_argument, &longOptFlag, PROPERTY},
        {"check-compat", no_argument, &longOptFlag, CHECK_COMPAT},
        {"dirmap", required_argument, &longOptFlag, DIR_MAP},
        {"kernel", required_argument, &longOptFlag, KERNEL},
        {0, 0, 0, 0}};
    std::map<int, Option> shortopts{
        {'h', HELP}, {'D', PROPERTY}, {'c', CHECK_COMPAT},
    };
    for (;;) {
        int c = getopt_long(argc, argv, "hcD:", longopts.data(), &optionIndex);
        if (c == -1) {
            break;
        }
        std::string argValue = optarg ? optarg : std::string{};
        if (c == 0) {
            ret.emplace(static_cast<Option>(longOptFlag), std::move(argValue));
        } else {
            ret.emplace(shortopts[c], std::move(argValue));
        }
    }
    if (optind < argc) {
        // see non option
        std::cerr << "unrecognized option `" << argv[optind] << "'" << std::endl;
        return {{HELP, ""}};
    }
    return ret;
}

template <typename T>
std::map<std::string, std::string> splitArgs(const T& args, char split) {
    std::map<std::string, std::string> ret;
    for (const auto& arg : args) {
        auto pos = arg.find(split);
        auto key = arg.substr(0, pos);
        auto value = pos == std::string::npos ? std::string{} : arg.substr(pos + 1);
        ret[key] = value;
    }
    return ret;
}
template <typename T>
Properties getProperties(const T& args) {
    return splitArgs(args, '=');
}

template <typename T>
Dirmap getDirmap(const T& args) {
    return splitArgs(args, ':');
}

template <typename T>
std::shared_ptr<StaticRuntimeInfo> getRuntimeInfo(const T& args) {
    auto ret = std::make_shared<StaticRuntimeInfo>();
    if (std::distance(args.begin(), args.end()) > 1) {
        std::cerr << "Error: Can't have multiple --kernel options" << std::endl;
        return nullptr;
    }
    auto pair = android::base::Split(*args.begin(), ":");
    if (pair.size() != 2) {
        std::cerr << "Error: Invalid --kernel" << std::endl;
        return nullptr;
    }
    if (!parse(pair[0], &ret->kernelVersion)) {
        std::cerr << "Error: Cannot parse " << pair[0] << " as kernel version" << std::endl;
        return nullptr;
    }
    ret->kernelConfigFile = std::move(pair[1]);
    return ret;
}

int usage(const char* me) {
    std::cerr
        << me << ": check VINTF metadata." << std::endl
        << "    Options:" << std::endl
        << "        --dump-file-list: Dump a list of directories / files on device" << std::endl
        << "                that is required to be used by --check-compat." << std::endl
        << "        -c, --check-compat: check compatibility for files under the root" << std::endl
        << "                directory specified by --root-dir." << std::endl
        << "        --rootdir=<dir>: specify root directory for all metadata. Same as " << std::endl
        << "                --dirmap /:<dir>" << std::endl
        << "        -D, --property <key>=<value>: specify sysprops." << std::endl
        << "        --dirmap </system:/dir/to/system> [--dirmap </vendor:/dir/to/vendor>[...]]"
        << std::endl
        << "                Map partitions to directories. Cannot be specified with --rootdir."
        << "        --kernel <x.y.z:path/to/config>" << std::endl
        << "                Use the given kernel version and config to check. If" << std::endl
        << "                unspecified, kernel requirements are skipped." << std::endl
        << std::endl
        << "        --help: show this message." << std::endl
        << std::endl
        << "    Example:" << std::endl
        << "        # Get the list of required files." << std::endl
        << "        " << me << " --dump-file-list > /tmp/files.txt" << std::endl
        << "        # Pull from ADB, or use your own command to extract files from images"
        << std::endl
        << "        ROOTDIR=/tmp/device/" << std::endl
        << "        cat /tmp/files.txt | xargs -I{} bash -c \"mkdir -p $ROOTDIR`dirname {}` && adb "
           "pull {} $ROOTDIR{}\""
        << std::endl
        << "        # Check compatibility." << std::endl
        << "        " << me << " --check-compat --rootdir=$ROOTDIR \\" << std::endl
        << "            --property ro.product.first_api_level=`adb shell getprop "
           "ro.product.first_api_level` \\"
        << std::endl
        << "            --property ro.boot.product.hardware.sku=`adb shell getprop "
           "ro.boot.product.hardware.sku`"
        << std::endl;
    return EX_USAGE;
}

int checkAllFiles(const Dirmap& dirmap, const Properties& props,
                  std::shared_ptr<StaticRuntimeInfo> runtimeInfo, std::string* error) {
    auto hostPropertyFetcher = std::make_unique<PresetPropertyFetcher>();
    hostPropertyFetcher->setProperties(props);

    CheckFlags::Type flags = CheckFlags::DEFAULT;
    if (!runtimeInfo) flags = flags.disableRuntimeInfo();

    auto vintfObject =
        VintfObject::Builder()
            .setFileSystem(std::make_unique<HostFileSystem>(dirmap))
            .setPropertyFetcher(std::move(hostPropertyFetcher))
            .setRuntimeInfoFactory(std::make_unique<StaticRuntimeInfoFactory>(runtimeInfo))
            .build();
    return vintfObject->checkCompatibility(error, flags);
}

}  // namespace details
}  // namespace vintf
}  // namespace android

int main(int argc, char** argv) {
    using namespace android::vintf;
    using namespace android::vintf::details;
    // legacy usage: check_vintf <manifest.xml> <matrix.xml>
    if (argc == 3) {
        int ret = checkCompatibilityForFiles(argv[1], argv[2]);
        if (ret >= 0) return ret;
    }

    Args args = parseArgs(argc, argv);

    if (!iterateValues(args, HELP).empty()) {
        return usage(argv[0]);
    }

    if (!iterateValues(args, DUMP_FILE_LIST).empty()) {
        for (const auto& file : dumpFileList()) {
            std::cout << file << std::endl;
        }
        return 0;
    }

    auto checkCompat = iterateValues(args, CHECK_COMPAT);
    if (checkCompat.empty()) {
        return usage(argv[0]);
    }

    auto rootdirs = iterateValues(args, ROOTDIR);
    if (!rootdirs.empty()) {
        if (std::distance(rootdirs.begin(), rootdirs.end()) > 1) {
            std::cerr << "Error: Can't have multiple --rootdir options" << std::endl;
            return usage(argv[0]);
        }
        args.emplace(DIR_MAP, "/:" + *rootdirs.begin());
    }

    auto properties = getProperties(iterateValues(args, PROPERTY));
    auto dirmap = getDirmap(iterateValues(args, DIR_MAP));

    std::shared_ptr<StaticRuntimeInfo> runtimeInfo;
    auto kernelArgs = iterateValues(args, KERNEL);
    if (!kernelArgs.empty()) {
        runtimeInfo = getRuntimeInfo(kernelArgs);
        if (runtimeInfo == nullptr) {
            return usage(argv[0]);
        }
    }

    std::string error;
    if (dirmap.empty()) {
        std::cerr << "Missing --rootdir or --dirmap option." << std::endl;
        return usage(argv[0]);
    }

    int compat = checkAllFiles(dirmap, properties, runtimeInfo, &error);

    if (compat == COMPATIBLE) {
        std::cout << "COMPATIBLE" << std::endl;
        return EX_OK;
    }
    if (compat == INCOMPATIBLE) {
        std::cerr << "Error: files are incompatible: " << error << std::endl;
        std::cout << "INCOMPATIBLE" << std::endl;
        return EX_DATAERR;
    }
    std::cerr << "Error: " << strerror(-compat) << ": " << error << std::endl;
    return EX_SOFTWARE;
}
