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

#include <algorithm>

#include "MapValueIterator.h"
#include "constants-private.h"
#include "utils.h"

namespace android {
namespace vintf {

using details::convertLegacyInstanceIntoFqInstance;

bool MatrixHal::isValid(std::string* error) const {
    bool success = true;

    // Check legacy instances (i.e. <version> + <interface> + <instance>) can be
    // converted into FqInstance because forEachInstance relies on FqInstance.
    // Because <version> is a range, check both ends of the range.
    for (const auto& vr : versionRanges) {
        for (const auto& v : {vr.minVer(), vr.maxVer()}) {
            for (const auto& intf : iterateValues(interfaces)) {
                intf.forEachInstance(
                    [&](const auto& interface, const auto& instance, bool /*isRegex*/) {
                        if (!convertLegacyInstanceIntoFqInstance(getName(), v, interface, instance,
                                                                 format, error)
                                 .has_value()) {
                            success = false;
                        }
                        return true;  // continue
                    });
            }
        }
    }

    return success;
}

bool MatrixHal::operator==(const MatrixHal &other) const {
    if (format != other.format)
        return false;
    if (name != other.name)
        return false;
    if (versionRanges != other.versionRanges)
        return false;
    if (interfaces != other.interfaces)
        return false;
    // do not compare optional
    return true;
}

bool MatrixHal::containsVersion(const Version& version) const {
    for (VersionRange vRange : versionRanges) {
        if (vRange.contains(version)) return true;
    }
    return false;
}

bool MatrixHal::forEachInstance(const std::function<bool(const MatrixInstance&)>& func) const {
    for (const auto& vr : versionRanges) {
        if (!forEachInstance(vr, func)) {
            return false;
        }
    }
    return true;
}

bool MatrixHal::forEachInstance(const VersionRange& vr,
                                const std::function<bool(const MatrixInstance&)>& func) const {
    for (const auto& intf : iterateValues(interfaces)) {
        bool cont =
            intf.forEachInstance([&](const auto& interface, const auto& instance, bool isRegex) {
                // TODO(b/73556059): Store MatrixInstance as well to avoid creating temps
                FqInstance fqInstance;
                if (fqInstance.setTo(getName(), vr.majorVer, vr.minMinor, interface, instance)) {
                    if (!func(MatrixInstance(format, std::move(fqInstance), VersionRange(vr),
                                             optional, isRegex))) {
                        return false;
                    }
                }
                return true;
            });
        if (!cont) {
            return false;
        }
    }
    return true;
}

bool MatrixHal::forEachInstance(
    const std::function<bool(const std::vector<VersionRange>&, const std::string&,
                             const std::string&, bool isRegex)>& func) const {
    for (const auto& intf : iterateValues(interfaces)) {
        bool cont =
            intf.forEachInstance([&](const auto& interface, const auto& instance, bool isRegex) {
                return func(this->versionRanges, interface, instance, isRegex);
            });
        if (!cont) {
            return false;
        }
    }
    return true;
}

bool MatrixHal::isCompatible(const std::set<FqInstance>& providedInstances,
                             const std::set<Version>& providedVersions) const {
    // <version>'s are related by OR.
    return std::any_of(versionRanges.begin(), versionRanges.end(), [&](const VersionRange& vr) {
        return isCompatible(vr, providedInstances, providedVersions);
    });
}

bool MatrixHal::isCompatible(const VersionRange& vr, const std::set<FqInstance>& providedInstances,
                             const std::set<Version>& providedVersions) const {
    bool hasAnyInstance = false;
    bool versionUnsatisfied = false;

    // Look at each interface/instance, and ensure that they are in providedInstances.
    forEachInstance(vr, [&](const MatrixInstance& matrixInstance) {
        hasAnyInstance = true;

        versionUnsatisfied |=
            !std::any_of(providedInstances.begin(), providedInstances.end(),
                         [&](const FqInstance& providedInstance) {
                             return matrixInstance.isSatisfiedBy(providedInstance);
                         });

        return !versionUnsatisfied;  // if any interface/instance is unsatisfied, break
    });

    if (hasAnyInstance) {
        return !versionUnsatisfied;
    }

    // In some cases (e.g. tests and native HALs), compatibility matrix doesn't specify
    // any instances. Check versions only.
    return std::any_of(
        providedVersions.begin(), providedVersions.end(),
        [&](const auto& providedVersion) { return vr.supportedBy(providedVersion); });
}

void MatrixHal::setOptional(bool o) {
    this->optional = o;
}

void MatrixHal::insertVersionRanges(const std::vector<VersionRange>& other) {
    for (const VersionRange& otherVr : other) {
        auto existingVr = std::find_if(this->versionRanges.begin(), this->versionRanges.end(),
                                       [&](const auto& e) { return e.overlaps(otherVr); });

        if (existingVr == this->versionRanges.end()) {
            this->versionRanges.push_back(otherVr);
        } else {
            existingVr->minMinor = std::min(existingVr->minMinor, otherVr.minMinor);
            existingVr->maxMinor = std::max(existingVr->maxMinor, otherVr.maxMinor);
        }
    }
}

void MatrixHal::insertInstance(const std::string& interface, const std::string& instance,
                               bool isRegex) {
    auto it = interfaces.find(interface);
    if (it == interfaces.end())
        it = interfaces.emplace(interface, HalInterface{interface, {}}).first;
    it->second.insertInstance(instance, isRegex);
}

size_t MatrixHal::instancesCount() const {
    size_t count = 0;
    forEachInstance([&](const MatrixInstance&) {
        ++count;
        return true;  // continue;
    });
    return count;
}

bool MatrixHal::removeInstance(const std::string& interface, const std::string& instance,
                               bool isRegex) {
    auto it = interfaces.find(interface);
    if (it == interfaces.end()) return false;
    bool removed = it->second.removeInstance(instance, isRegex);
    if (!it->second.hasAnyInstance()) interfaces.erase(it);
    return removed;
}

void MatrixHal::clearInstances() {
    this->interfaces.clear();
}

} // namespace vintf
} // namespace android
