/*
 * 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 "Hash.h"

#include <algorithm>
#include <fstream>
#include <iomanip>
#include <map>
#include <regex>
#include <sstream>

#include <android-base/logging.h>
#include <openssl/sha.h>

namespace android {

const std::vector<uint8_t> Hash::kEmptyHash = std::vector<uint8_t>(SHA256_DIGEST_LENGTH, 0);

Hash& Hash::getMutableHash(const std::string& path) {
    static std::map<std::string, Hash> hashes;

    auto it = hashes.find(path);

    if (hashes.find(path) == hashes.end()) {
        it = hashes.insert(it, {path, Hash(path)});
    }

    return it->second;
}

const Hash& Hash::getHash(const std::string& path) {
    return getMutableHash(path);
}

void Hash::clearHash(const std::string& path) {
    getMutableHash(path).mHash = kEmptyHash;
}

static std::vector<uint8_t> sha256File(const std::string &path) {
    std::ifstream stream(path);
    std::stringstream fileStream;
    fileStream << stream.rdbuf();
    std::string fileContent = fileStream.str();

    std::vector<uint8_t> ret = std::vector<uint8_t>(SHA256_DIGEST_LENGTH);

    SHA256(reinterpret_cast<const uint8_t *>(fileContent.c_str()),
            fileContent.size(), ret.data());

    return ret;
}

Hash::Hash(const std::string &path)
  : mPath(path),
    mHash(sha256File(path)) {}

std::string Hash::hexString(const std::vector<uint8_t> &hash) {
    std::ostringstream s;
    s << std::hex << std::setfill('0');
    for (uint8_t i : hash) {
        s << std::setw(2) << static_cast<int>(i);
    }
    return s.str();
}

std::string Hash::hexString() const {
    return hexString(mHash);
}

const std::vector<uint8_t> &Hash::raw() const {
    return mHash;
}

const std::string &Hash::getPath() const {
    return mPath;
}

#define HASH "([0-9a-f]+)"
#define FQNAME "([^\\s]+)"
#define SPACES " +"
#define MAYBE_SPACES " *"
#define OPTIONAL_COMMENT "(?:#.*)?"
static const std::regex kHashLine(
    "(?:"
        MAYBE_SPACES HASH SPACES FQNAME MAYBE_SPACES
    ")?"
    OPTIONAL_COMMENT);

struct HashFile {
    static const HashFile *parse(const std::string &path, std::string *err) {
        static std::map<std::string, HashFile*> hashfiles;
        auto it = hashfiles.find(path);

        if (it == hashfiles.end()) {
            it = hashfiles.insert(it, {path, readHashFile(path, err)});
        }

        return it->second;
    }

    std::vector<std::string> lookup(const std::string &fqName) const {
        auto it = hashes.find(fqName);

        if (it == hashes.end()) {
            return {};
        }

        return it->second;
    }

private:
    static HashFile *readHashFile(const std::string &path, std::string *err) {
        std::ifstream stream(path);
        if (!stream) {
            return nullptr;
        }

        HashFile *file = new HashFile();
        file->path = path;

        std::string line;
        while(std::getline(stream, line)) {
            std::smatch match;
            bool valid = std::regex_match(line, match, kHashLine);

            if (!valid) {
                *err = "Error reading line from " + path + ": " + line;
                delete file;
                return nullptr;
            }

            CHECK_EQ(match.size(), 3u);

            std::string hash = match.str(1);
            std::string fqName = match.str(2);

            if (hash.size() == 0 && fqName.size() == 0) {
                continue;
            }

            if (hash.size() == 0 || fqName.size() == 0) {
                *err = "Hash or fqName empty on " + path + ": " + line;
                delete file;
                return nullptr;
            }

            file->hashes[fqName].push_back(hash);
        }
        return file;
    }

    std::string path;
    std::map<std::string,std::vector<std::string>> hashes;
};

std::vector<std::string> Hash::lookupHash(const std::string& path, const std::string& interfaceName,
                                          std::string* err, bool* fileExists) {
    *err = "";
    const HashFile *file = HashFile::parse(path, err);

    if (file == nullptr || err->size() > 0) {
        if (fileExists != nullptr) *fileExists = false;
        return {};
    }

    if (fileExists != nullptr) *fileExists = true;

    return file->lookup(interfaceName);
}

}  // android
