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

#include <iostream>
#include <utility>

#include <android-base/logging.h>
#include <android-base/strings.h>

#include "parse_string.h"
#include "parse_xml.h"
#include "utils.h"

namespace android {
namespace vintf {

using details::mergeField;

bool CompatibilityMatrix::add(MatrixHal&& halToAdd, std::string*) {
    CHECK(addInternal(std::move(halToAdd)) != nullptr);
    return true;
}

bool CompatibilityMatrix::addAllHals(CompatibilityMatrix* other, std::string*) {
    std::string internalError;
    for (auto& pair : other->mHals) {
        CHECK(add(std::move(pair.second), &internalError)) << internalError;
    }
    other->mHals.clear();
    return true;
}

bool CompatibilityMatrix::addKernel(MatrixKernel&& kernel, std::string* error) {
    if (mType != SchemaType::FRAMEWORK) {
        if (error) {
            *error = "Cannot add <kernel> to a " + to_string(mType) + " compatibility matrix.";
        }
        return false;
    }

    if (kernel.getSourceMatrixLevel() == Level::UNSPECIFIED) {
        kernel.setSourceMatrixLevel(level());
    }

    auto it = framework.mKernels.begin();
    for (; it != framework.mKernels.end(); ++it) {
        if (it->getSourceMatrixLevel() != kernel.getSourceMatrixLevel()) {
            continue;
        }
        if (it->minLts() == kernel.minLts()) {
            break;
        }
        if (it->minLts().dropMinor() == kernel.minLts().dropMinor()) {
            if (error) {
                *error = "Kernel version mismatch; for level " +
                         to_string(kernel.getSourceMatrixLevel()) + ", cannot add " +
                         to_string(kernel.minLts()) + " because " + to_string(it->minLts()) +
                         " was added.";
            }
            return false;
        }
    }

    bool seenVersion = it != framework.mKernels.end();

    if (seenVersion) {
        // If no conditions, must be the first among the same minLts
        // because O libvintf only checks the first <kernel> tag that version matches.
        if (kernel.conditions().empty()) {
            // Found first <kernel> with the same minLts.
            // Append config if it does not have <condition>s, else error.
            if (it->conditions().empty()) {
                const auto& configs = kernel.configs();
                it->mConfigs.insert(it->mConfigs.end(), configs.begin(), configs.end());
            } else {
                if (error) {
                    *error =
                        "Base compatibility matrix has <condition> for the first <kernel> "
                        "with minlts " +
                        to_string(kernel.minLts()) + " for unknown reason.";
                }
                return false;
            }
            return true;
        }
    } else {
        // First <kernel> of a minLts must not have <condition>'s for backwards compatibility
        // with O libvintf.
        if (!kernel.conditions().empty()) {
            framework.mKernels.push_back(MatrixKernel(KernelVersion{kernel.minLts()}, {}));
        }
    }

    framework.mKernels.push_back(std::move(kernel));
    return true;
}

SchemaType CompatibilityMatrix::type() const {
    return mType;
}

Level CompatibilityMatrix::level() const {
    return mLevel;
}

status_t CompatibilityMatrix::fetchAllInformation(const FileSystem* fileSystem,
                                                  const std::string& path, std::string* error) {
    return details::fetchAllInformation(fileSystem, path, gCompatibilityMatrixConverter, this,
                                        error);
}

std::string CompatibilityMatrix::getXmlSchemaPath(const std::string& xmlFileName,
                                                  const Version& version) const {
    using std::literals::string_literals::operator""s;
    auto range = getXmlFiles(xmlFileName);
    for (auto it = range.first; it != range.second; ++it) {
        const MatrixXmlFile& matrixXmlFile = it->second;
        if (matrixXmlFile.versionRange().contains(version)) {
            if (!matrixXmlFile.overriddenPath().empty()) {
                return matrixXmlFile.overriddenPath();
            }
            return "/"s + (type() == SchemaType::DEVICE ? "vendor" : "system") + "/etc/" +
                   xmlFileName + "_V" + std::to_string(matrixXmlFile.versionRange().majorVer) +
                   "_" + std::to_string(matrixXmlFile.versionRange().maxMinor) + "." +
                   to_string(matrixXmlFile.format());
        }
    }
    return "";
}

// Split existingHal into a HAL that contains only interface/instance and a HAL
// that does not contain it. Return the HAL that contains only interface/instance.
// - Return nullptr if existingHal does not contain interface/instance
// - Return existingHal if existingHal contains only interface/instance
// - Remove interface/instance from existingHal, and return a new MatrixHal (that is added
//   to "this") that contains only interface/instance.
MatrixHal* CompatibilityMatrix::splitInstance(MatrixHal* existingHal, const std::string& interface,
                                              const std::string& instanceOrPattern, bool isRegex) {
    bool found = false;
    bool foundOthers = false;
    existingHal->forEachInstance([&](const auto& matrixInstance) {
        bool interfaceMatch = matrixInstance.interface() == interface;
        bool instanceMatch = false;
        if (matrixInstance.isRegex() && isRegex) {
            instanceMatch = (matrixInstance.regexPattern() == instanceOrPattern);
        } else if (!matrixInstance.isRegex() && !isRegex) {
            instanceMatch = (matrixInstance.exactInstance() == instanceOrPattern);
        }

        bool match = interfaceMatch && instanceMatch;

        found |= match;
        foundOthers |= (!match);

        return !found || !foundOthers;
    });

    if (!found) {
        return nullptr;
    }

    if (!foundOthers) {
        return existingHal;
    }

    existingHal->removeInstance(interface, instanceOrPattern, isRegex);
    MatrixHal copy = *existingHal;
    copy.clearInstances();
    copy.insertInstance(interface, instanceOrPattern, isRegex);

    return addInternal(std::move(copy));
}

// Add all package@other_version::interface/instance as an optional instance.
// If package@this_version::interface/instance is in this (that is, some instance
// with the same package and interface and instance exists), then other_version is
// considered a possible replacement to this_version.
// See LibVintfTest.AddOptionalHal* tests for details.
bool CompatibilityMatrix::addAllHalsAsOptional(CompatibilityMatrix* other, std::string* error) {
    if (other == nullptr || other->level() <= level()) {
        return true;
    }

    for (auto& pair : other->mHals) {
        const std::string& name = pair.first;
        MatrixHal& halToAdd = pair.second;

        std::set<std::pair<std::string, std::string>> insertedInstances;
        std::set<std::pair<std::string, std::string>> insertedRegex;
        auto existingHals = getHals(name);

        halToAdd.forEachInstance([&](const std::vector<VersionRange>& versionRanges,
                                     const std::string& interface,
                                     const std::string& instanceOrPattern, bool isRegex) {
            for (auto* existingHal : existingHals) {
                // Ignore HALs with different format.
                if (halToAdd.format != existingHal->format) {
                    continue;
                }

                MatrixHal* splitInstance =
                    this->splitInstance(existingHal, interface, instanceOrPattern, isRegex);
                if (splitInstance != nullptr) {
                    splitInstance->insertVersionRanges(versionRanges);
                    if (isRegex) {
                        insertedRegex.insert(std::make_pair(interface, instanceOrPattern));
                    } else {
                        insertedInstances.insert(std::make_pair(interface, instanceOrPattern));
                    }
                }
            }
            return true;
        });

        // Add the remaining instances.
        for (const auto& pair : insertedInstances) {
            halToAdd.removeInstance(pair.first, pair.second, false /* isRegex */);
        }
        for (const auto& pair : insertedRegex) {
            halToAdd.removeInstance(pair.first, pair.second, true /* isRegex */);
        }

        if (halToAdd.instancesCount() > 0) {
            halToAdd.setOptional(true);
            if (!add(std::move(halToAdd))) {
                if (error) {
                    *error = "Cannot add HAL " + name + " for unknown reason.";
                }
                return false;
            }
        }
    }
    return true;
}

bool CompatibilityMatrix::addAllXmlFilesAsOptional(CompatibilityMatrix* other, std::string* error) {
    if (other == nullptr || other->level() <= level()) {
        return true;
    }
    for (auto& pair : other->mXmlFiles) {
        const std::string& name = pair.first;
        MatrixXmlFile& xmlFileToAdd = pair.second;

        xmlFileToAdd.mOptional = true;
        if (!addXmlFile(std::move(xmlFileToAdd))) {
            if (error) {
                *error = "Cannot add XML File " + name + " for unknown reason.";
            }
            return false;
        }
    }
    return true;
}

// Merge Kernel. See KernelInfo::getMatchedKernelRequirements for details on compatibility checks.
bool CompatibilityMatrix::addAllKernels(CompatibilityMatrix* other, std::string* error) {
    for (MatrixKernel& kernel : other->framework.mKernels) {
        if (kernel.getSourceMatrixLevel() == Level::UNSPECIFIED) {
            kernel.setSourceMatrixLevel(other->level());
        }
        KernelVersion ver = kernel.minLts();
        if (!addKernel(std::move(kernel), error)) {
            if (error) {
                *error = "Cannot add kernel version " + to_string(ver) + ": " + *error;
            }
            return false;
        }
    }
    return true;
}

bool CompatibilityMatrix::addSepolicy(CompatibilityMatrix* other, std::string* error) {
    bool success = mergeField(&this->framework.mSepolicy, &other->framework.mSepolicy);
    if (!success && error) *error = "<sepolicy> is already defined";
    return success;
}

bool CompatibilityMatrix::addAvbMetaVersion(CompatibilityMatrix* other, std::string* error) {
    bool success = mergeField(&this->framework.mAvbMetaVersion, &other->framework.mAvbMetaVersion);
    if (!success && error) *error = "<avb><vbmeta-version> is already defined";
    return success;
}

bool CompatibilityMatrix::addVndk(CompatibilityMatrix* other, std::string* error) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
    bool success = mergeField(&this->device.mVndk, &other->device.mVndk);
#pragma clang diagnostic pop
    if (!success && error) *error = "<vndk> is already defined";
    return success;
}

bool CompatibilityMatrix::addVendorNdk(CompatibilityMatrix* other, std::string* error) {
    bool success = mergeField(&this->device.mVendorNdk, &other->device.mVendorNdk);
    if (!success && error) *error = "<vendor-ndk> is already defined";
    return success;
}

bool CompatibilityMatrix::addSystemSdk(CompatibilityMatrix* other, std::string* /* error */) {
    this->device.mSystemSdk.addAll(&other->device.mSystemSdk);
    return true;
}

bool operator==(const CompatibilityMatrix &lft, const CompatibilityMatrix &rgt) {
    // ignore fileName().
    return lft.mType == rgt.mType && lft.mLevel == rgt.mLevel && lft.mHals == rgt.mHals &&
           lft.mXmlFiles == rgt.mXmlFiles &&
           (lft.mType != SchemaType::DEVICE ||
            (
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
                lft.device.mVndk == rgt.device.mVndk &&
#pragma clang diagnostic pop
                lft.device.mVendorNdk == rgt.device.mVendorNdk &&
                lft.device.mSystemSdk == rgt.device.mSystemSdk)) &&
           (lft.mType != SchemaType::FRAMEWORK ||
            (lft.framework.mKernels == rgt.framework.mKernels &&
             lft.framework.mSepolicy == rgt.framework.mSepolicy &&
             lft.framework.mAvbMetaVersion == rgt.framework.mAvbMetaVersion));
}

std::unique_ptr<CompatibilityMatrix> CompatibilityMatrix::combine(
    Level deviceLevel, std::vector<CompatibilityMatrix>* matrices, std::string* error) {
    // Check type.
    for (const auto& e : *matrices) {
        if (e.type() != SchemaType::FRAMEWORK) {
            if (error) {
                *error = "File \"" + e.fileName() + "\" is not a framework compatibility matrix.";
                return nullptr;
            }
        }
    }

    // Matrices with unspecified (empty) level are auto-filled with deviceLevel.
    for (auto& e : *matrices) {
        if (e.level() == Level::UNSPECIFIED) {
            e.mLevel = deviceLevel;
        }
    }

    // Add from low to high FCM version so that optional <kernel> requirements are added correctly.
    // See comment in addAllAsOptional.
    std::sort(matrices->begin(), matrices->end(),
              [](const auto& x, const auto& y) { return x.level() < y.level(); });

    auto baseMatrix = std::make_unique<CompatibilityMatrix>();
    baseMatrix->mLevel = deviceLevel;
    baseMatrix->mType = SchemaType::FRAMEWORK;

    std::vector<std::string> parsedFiles;
    for (auto& e : *matrices) {
        if (e.level() < deviceLevel) {
            continue;
        }

        bool success = false;
        if (e.level() == deviceLevel) {
            success = baseMatrix->addAll(&e, error);
        } else {
            success = baseMatrix->addAllAsOptional(&e, error);
        }
        if (!success) {
            if (error) {
                *error = "Conflict when merging \"" + e.fileName() + "\": " + *error + "\n" +
                         "Previous files:\n" + base::Join(parsedFiles, "\n");
            }
            return nullptr;
        }
        parsedFiles.push_back(e.fileName());
    }

    return baseMatrix;
}

std::unique_ptr<CompatibilityMatrix> CompatibilityMatrix::combineDeviceMatrices(
    std::vector<CompatibilityMatrix>* matrices, std::string* error) {
    auto baseMatrix = std::make_unique<CompatibilityMatrix>();
    baseMatrix->mType = SchemaType::DEVICE;

    std::vector<std::string> parsedFiles;
    for (auto& e : *matrices) {
        bool success = baseMatrix->addAll(&e, error);
        if (!success) {
            if (error) {
                *error = "Conflict when merging \"" + e.fileName() + "\": " + *error + "\n" +
                         "Previous files:\n" + base::Join(parsedFiles, "\n");
            }
            return nullptr;
        }
        parsedFiles.push_back(e.fileName());
    }
    return baseMatrix;
}

bool CompatibilityMatrix::addAll(CompatibilityMatrix* inputMatrix, std::string* error) {
    if (!addAllHals(inputMatrix, error) || !addAllXmlFiles(inputMatrix, error) ||
        !addAllKernels(inputMatrix, error) || !addSepolicy(inputMatrix, error) ||
        !addAvbMetaVersion(inputMatrix, error) || !addVndk(inputMatrix, error) ||
        !addVendorNdk(inputMatrix, error) || !addSystemSdk(inputMatrix, error)) {
        if (error) {
            *error = "File \"" + inputMatrix->fileName() + "\" cannot be added: " + *error + ".";
        }
        return false;
    }
    return true;
}

bool CompatibilityMatrix::addAllAsOptional(CompatibilityMatrix* inputMatrix, std::string* error) {
    if (!addAllHalsAsOptional(inputMatrix, error) ||
        !addAllXmlFilesAsOptional(inputMatrix, error) || !addAllKernels(inputMatrix, error)) {
        if (error) {
            *error = "File \"" + inputMatrix->fileName() + "\" cannot be added: " + *error;
        }
        return false;
    }
    // ignore <sepolicy> requirement from higher level
    // ignore <avb> requirement from higher level
    return true;
}

bool CompatibilityMatrix::forEachInstanceOfVersion(
    HalFormat format, const std::string& package, const Version& expectVersion,
    const std::function<bool(const MatrixInstance&)>& func) const {
    for (const MatrixHal* hal : getHals(package)) {
        bool cont = hal->forEachInstance([&](const MatrixInstance& matrixInstance) {
            if (matrixInstance.format() == format &&
                matrixInstance.versionRange().contains(expectVersion)) {
                return func(matrixInstance);
            }
            return true;
        });
        if (!cont) return false;
    }
    return true;
}

bool CompatibilityMatrix::matchInstance(HalFormat format, const std::string& halName,
                                        const Version& version, const std::string& interfaceName,
                                        const std::string& instance) const {
    bool found = false;
    (void)forEachInstanceOfInterface(format, halName, version, interfaceName,
                                     [&found, &instance](const auto& e) {
                                         found |= (e.matchInstance(instance));
                                         return !found;  // if not found, continue
                                     });
    return found;
}

std::string CompatibilityMatrix::getVendorNdkVersion() const {
    return type() == SchemaType::DEVICE ? device.mVendorNdk.version() : "";
}

Level CompatibilityMatrix::getSourceMatrixLevel(const MatrixKernel* matrixKernel) const {
    CHECK(std::find_if(framework.mKernels.begin(), framework.mKernels.end(),
                       [matrixKernel](const auto& e) { return &e == matrixKernel; }) !=
          framework.mKernels.end());
    Level ret = matrixKernel->getSourceMatrixLevel();
    if (ret != Level::UNSPECIFIED) return ret;
    return level();
}

} // namespace vintf
} // namespace android
