/*
// Copyright (c) 2018 Intel Corporation
//
// 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 <Utils.hpp>
#include <Overlay.hpp>
#include <dbus/properties.hpp>
#include <nlohmann/json.hpp>
#include <fstream>
#include <future>
#include <regex>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
#include <dbus/connection.hpp>
#include <VariantVisitors.hpp>
#include <experimental/filesystem>

constexpr const char *OUTPUT_DIR = "/var/configuration/";
constexpr const char *CONFIGURATION_DIR = "/usr/share/configurations";
constexpr const char *TEMPLATE_CHAR = "$";
constexpr const size_t PROPERTIES_CHANGED_UNTIL_FLUSH_COUNT = 20;
constexpr const size_t MAX_MAPPER_DEPTH = 99;
constexpr const size_t SLEEP_AFTER_PROPERTIES_CHANGE_SECONDS = 5;

namespace fs = std::experimental::filesystem;
struct cmp_str
{
    bool operator()(const char *a, const char *b) const
    {
        return std::strcmp(a, b) < 0;
    }
};

// underscore T for collison with dbus c api
enum class probe_type_codes
{
    FALSE_T,
    TRUE_T,
    AND,
    OR,
    FOUND,
    MATCH_ONE
};
const static boost::container::flat_map<const char *, probe_type_codes, cmp_str>
    PROBE_TYPES{{{"FALSE", probe_type_codes::FALSE_T},
                 {"TRUE", probe_type_codes::TRUE_T},
                 {"AND", probe_type_codes::AND},
                 {"OR", probe_type_codes::OR},
                 {"FOUND", probe_type_codes::FOUND},
                 {"MATCH_ONE", probe_type_codes::MATCH_ONE}}};

using GetSubTreeType = std::vector<
    std::pair<std::string,
              std::vector<std::pair<std::string, std::vector<std::string>>>>>;

using ManagedObjectType = boost::container::flat_map<
    dbus::object_path,
    boost::container::flat_map<
        std::string,
        boost::container::flat_map<std::string, dbus::dbus_variant>>>;

boost::container::flat_map<
    std::string,
    std::vector<boost::container::flat_map<std::string, dbus::dbus_variant>>>
    DBUS_PROBE_OBJECTS;
std::vector<std::string> PASSED_PROBES;

// todo: pass this through nicer
std::shared_ptr<dbus::connection> SYSTEM_BUS;

std::regex ILLEGAL_DBUS_REGEX("[^A-Za-z0-9_]");

void registerCallbacks(
    std::vector<std::pair<std::unique_ptr<dbus::match>,
                          std::shared_ptr<dbus::filter>>> &dbusMatches,
    nlohmann::json &systemConfiguration, dbus::DbusObjectServer &objServer);

// calls the mapper to find all exposed objects of an interface type
// and creates a vector<flat_map> that contains all the key value pairs
// getManagedObjects
bool findDbusObjects(
    std::shared_ptr<dbus::connection> connection,
    std::vector<boost::container::flat_map<std::string, dbus::dbus_variant>>
        &interfaceDevices,
    std::string interface)
{
    // todo: this is only static because the mapper is unreliable as of today
    static boost::container::flat_map<std::string,
                                      boost::container::flat_set<std::string>>
        connections;
    // find all connections in the mapper that expose a specific type
    static const dbus::endpoint mapper("xyz.openbmc_project.ObjectMapper",
                                       "/xyz/openbmc_project/object_mapper",
                                       "xyz.openbmc_project.ObjectMapper",
                                       "GetSubTree");
    dbus::message getMap = dbus::message::new_call(mapper);
    std::vector<std::string> objects = {interface};
    if (!getMap.pack("", MAX_MAPPER_DEPTH, objects))
    {
        std::cerr << "Pack Failed GetSensorSubtree\n";
        return false;
    }

    GetSubTreeType interfaceSubtree;
    size_t retries = 1;
    bool unpackStatus = false;
    // the mapper seems to hang occasionally, not responding, so we give it a
    // timeout and retries
    do
    {
        dbus::message getMapResp =
            connection->send(getMap, std::chrono::seconds(2));
        unpackStatus = getMapResp.unpack(interfaceSubtree);

    } while (retries-- && !unpackStatus);

    auto &interfaceConnections = connections[interface];
    if (!unpackStatus)
    {
        std::cerr << "Error communicating to mapper, using cached data if "
                     "available\n";
        if (interfaceConnections.empty())
        {
            return false;
        }
    }

    if (unpackStatus)
    {
        interfaceConnections.clear();
        for (auto &object : interfaceSubtree)
        {
            for (auto &connPair : object.second)
            {
                interfaceConnections.insert(connPair.first);
            }
        }
    }
    // iterate through the connections, adding creating individual device
    // dictionaries
    for (auto &conn : interfaceConnections)
    {
        auto managedObj =
            dbus::endpoint(conn, "/", "org.freedesktop.DBus.ObjectManager",
                           "GetManagedObjects");
        dbus::message getManagedObj = dbus::message::new_call(managedObj);
        ManagedObjectType managedInterface;
        retries = 1;
        unpackStatus = false;
        do
        {
            dbus::message getManagedObjResp = connection->send(getManagedObj);
            unpackStatus = getManagedObjResp.unpack(managedInterface);
        } while (retries-- && !unpackStatus);

        if (!unpackStatus)
        {
            std::cerr << "error getting managed object for device " << conn
                      << "\n";
            continue;
        }
        for (auto &interfaceManagedObj : managedInterface)
        {
            auto ifaceObjFind = interfaceManagedObj.second.find(interface);
            if (ifaceObjFind != interfaceManagedObj.second.end())
            {
                interfaceDevices.emplace_back(ifaceObjFind->second);
            }
        }
    }
    return true;
}

// probes interface dictionary for a key with a value that matches a regex
bool probeDbus(
    const std::string &interface,
    const std::map<std::string, nlohmann::json> &matches,
    std::vector<boost::container::flat_map<std::string, dbus::dbus_variant>>
        &devices,
    bool &foundProbe)
{
    auto &dbusObject = DBUS_PROBE_OBJECTS[interface];
    if (dbusObject.empty())
    {
        if (!findDbusObjects(SYSTEM_BUS, dbusObject, interface))
        {
            std::cerr << "Found no dbus objects with interface "
                      << interface << "\n";
            foundProbe = false;
            return false;
        }
    }
    foundProbe = true;

    bool foundMatch = false;
    for (auto &device : dbusObject)
    {
        bool deviceMatches = true;
        for (auto &match : matches)
        {
            auto deviceValue = device.find(match.first);
            if (deviceValue != device.end())
            {
                switch (match.second.type())
                {
                case nlohmann::json::value_t::string:
                {
                    std::regex search(match.second.get<std::string>());
                    std::smatch match;

                    // convert value to string respresentation
                    std::string probeValue = boost::apply_visitor(
                        [](const auto &x) {
                            return boost::lexical_cast<std::string>(x);
                        },
                        deviceValue->second);
                    if (!std::regex_search(probeValue, match, search))
                    {
                        deviceMatches = false;
                        break;
                    }
                    break;
                }
                case nlohmann::json::value_t::boolean:
                case nlohmann::json::value_t::number_unsigned:
                {
                    unsigned int probeValue = boost::apply_visitor(
                        VariantToUnsignedIntVisitor(), deviceValue->second);

                    if (probeValue != match.second.get<unsigned int>())
                    {
                        deviceMatches = false;
                    }
                    break;
                }
                case nlohmann::json::value_t::number_integer:
                {
                    int probeValue = boost::apply_visitor(VariantToIntVisitor(),
                                                          deviceValue->second);

                    if (probeValue != match.second.get<int>())
                    {
                        deviceMatches = false;
                    }
                    break;
                }
                case nlohmann::json::value_t::number_float:
                {
                    float probeValue = boost::apply_visitor(
                        VariantToFloatVisitor(), deviceValue->second);

                    if (probeValue != match.second.get<float>())
                    {
                        deviceMatches = false;
                    }
                    break;
                }
                }
            }
            else
            {
                deviceMatches = false;
                break;
            }
        }
        if (deviceMatches)
        {
            devices.emplace_back(
                boost::container::flat_map<std::string, dbus::dbus_variant>(
                    device));
            foundMatch = true;
            deviceMatches = false; // for next iteration
        }
    }
    return foundMatch;
}

// default probe entry point, iterates a list looking for specific types to
// call specific probe functions
bool probe(
    const std::vector<std::string> probeCommand,
    std::vector<boost::container::flat_map<std::string, dbus::dbus_variant>>
        &foundDevs)
{
    const static std::regex command(R"(\((.*)\))");
    std::smatch match;
    bool ret = false;
    bool matchOne = false;
    bool cur = true;
    probe_type_codes lastCommand = probe_type_codes::FALSE_T;

    for (auto &probe : probeCommand)
    {
        bool foundProbe = false;
        boost::container::flat_map<const char *, probe_type_codes,
                                   cmp_str>::const_iterator probeType;

        for (probeType = PROBE_TYPES.begin(); probeType != PROBE_TYPES.end();
             probeType++)
        {
            if (probe.find(probeType->first) != std::string::npos)
            {
                foundProbe = true;
                break;
            }
        }
        if (foundProbe)
        {
            switch (probeType->second)
            {
            case probe_type_codes::FALSE_T:
            {
                return false; // todo, actually evaluate?
                break;
            }
            case probe_type_codes::TRUE_T:
            {
                return true; // todo, actually evaluate?
                break;
            }
            case probe_type_codes::MATCH_ONE:
            {
                // set current value to last, this probe type shouldn't affect
                // the outcome
                cur = ret;
                matchOne = true;
                break;
            }
            /*case probe_type_codes::AND:
              break;
            case probe_type_codes::OR:
              break;
              // these are no-ops until the last command switch
              */
            case probe_type_codes::FOUND:
            {
                if (!std::regex_search(probe, match, command))
                {
                    std::cerr << "found probe sytax error " << probe << "\n";
                    return false;
                }
                std::string commandStr = *(match.begin() + 1);
                boost::replace_all(commandStr, "'", "");
                cur = (std::find(PASSED_PROBES.begin(), PASSED_PROBES.end(),
                                 commandStr) != PASSED_PROBES.end());
                break;
            }
            }
        }
        // look on dbus for object
        else
        {
            if (!std::regex_search(probe, match, command))
            {
                std::cerr << "dbus probe sytax error " << probe << "\n";
                return false;
            }
            std::string commandStr = *(match.begin() + 1);
            // convert single ticks and single slashes into legal json
            boost::replace_all(commandStr, "'", "\"");
            boost::replace_all(commandStr, R"(\)", R"(\\)");
            auto json = nlohmann::json::parse(commandStr, nullptr, false);
            if (json.is_discarded())
            {
                std::cerr << "dbus command sytax error " << commandStr << "\n";
                return false;
            }
            // we can match any (string, variant) property. (string, string)
            // does a regex
            std::map<std::string, nlohmann::json> dbusProbeMap =
                json.get<std::map<std::string, nlohmann::json>>();
            auto findStart = probe.find("(");
            if (findStart == std::string::npos)
            {
                return false;
            }
            std::string probeInterface = probe.substr(0, findStart);
            cur =
                probeDbus(probeInterface, dbusProbeMap, foundDevs, foundProbe);
        }

        // some functions like AND and OR only take affect after the
        // fact
        switch (lastCommand)
        {
        case probe_type_codes::AND:
            ret = cur && ret;
            break;
        case probe_type_codes::OR:
            ret = cur || ret;
            break;
        default:
            ret = cur;
            break;
        }
        lastCommand = probeType != PROBE_TYPES.end()
                          ? probeType->second
                          : probe_type_codes::FALSE_T;

        if (!foundProbe)
        {
            std::cerr << "Illegal probe type " << probe << "\n";
            return false;
        }
    }

    // probe passed, but empty device
    // todo: should this be done in main?
    if (ret && foundDevs.size() == 0)
    {
        foundDevs.emplace_back(
            boost::container::flat_map<std::string, dbus::dbus_variant>());
    }
    if (matchOne && foundDevs.size() > 1)
    {
        foundDevs.erase(foundDevs.begin() + 1, foundDevs.end());
    }
    return ret;
}

// this function is temporary, no need to have once dbus is solified.
void writeJsonFiles(nlohmann::json &systemConfiguration)
{
    std::experimental::filesystem::create_directory(OUTPUT_DIR);
    std::ofstream output(std::string(OUTPUT_DIR) + "system.json");
    output << systemConfiguration.dump(4);
    output.close();

    auto flat = nlohmann::json::array();
    for (auto &pair : nlohmann::json::iterator_wrapper(systemConfiguration))
    {
        auto value = pair.value();
        auto exposes = value.find("exposes");
        if (exposes != value.end())
        {
            for (auto &item : *exposes)
            {
                flat.push_back(item);
            }
        }
    }
    output = std::ofstream(std::string(OUTPUT_DIR) + "flattened.json");
    output << flat.dump(4);
    output.close();
}
// adds simple json types to interface's properties
void populateInterfaceFromJson(dbus::DbusInterface *iface, nlohmann::json dict,
                               dbus::DbusObjectServer &objServer)
{
    std::vector<std::pair<std::string, dbus::dbus_variant>> properties;
    static size_t flushCount = 0;

    for (auto &dictPair : nlohmann::json::iterator_wrapper(dict))
    {
        switch (dictPair.value().type())
        {
        case (nlohmann::json::value_t::boolean):
        {
            properties.emplace_back(std::string(dictPair.key()),
                                    dictPair.value().get<bool>());
            break;
        }
        case (nlohmann::json::value_t::number_integer):
        {
            properties.emplace_back(std::string(dictPair.key()),
                                    dictPair.value().get<int64_t>());
            break;
        }
        case (nlohmann::json::value_t::number_unsigned):
        {
            properties.emplace_back(std::string(dictPair.key()),
                                    dictPair.value().get<uint64_t>());
            break;
        }
        case (nlohmann::json::value_t::number_float):
        {
            properties.emplace_back(std::string(dictPair.key()),
                                    dictPair.value().get<float>());
            break;
        }
        case (nlohmann::json::value_t::string):
        {
            properties.emplace_back(std::string(dictPair.key()),
                                    dictPair.value().get<std::string>());
            break;
        }
        }
    }
    if (!properties.empty())
    {
        iface->set_properties(properties);

        // flush the queue after adding an amount of properties so we don't hang
        if (flushCount++ > PROPERTIES_CHANGED_UNTIL_FLUSH_COUNT)
        {
            objServer.flush();
            flushCount = 0;
        }
    }
}

void postToDbus(const nlohmann::json &systemConfiguration,
                dbus::DbusObjectServer &objServer)

{
    for (auto &boardPair :
         nlohmann::json::iterator_wrapper(systemConfiguration))
    {
        std::string boardKey = boardPair.key();
        auto boardValues = boardPair.value();
        auto findBoardType = boardValues.find("type");
        std::string boardType;
        if (findBoardType != boardValues.end() &&
            findBoardType->type() == nlohmann::json::value_t::string)
        {
            boardType = findBoardType->get<std::string>();
            std::regex_replace(boardType.begin(), boardType.begin(),
                               boardType.end(), ILLEGAL_DBUS_REGEX, "_");
        }
        else
        {
            std::cerr << "Unable to find type for " << boardKey
                      << " reverting to Chassis.\n";
            boardType = "Chassis";
        }

        std::regex_replace(boardKey.begin(), boardKey.begin(), boardKey.end(),
                           ILLEGAL_DBUS_REGEX, "_");
        std::string boardName =
            "/xyz/openbmc_project/Inventory/Item/" + boardType + "/" + boardKey;
        auto boardObject = objServer.add_object(boardName);

        auto boardIface = boardObject->add_interface(
            "xyz.openbmc_project.Configuration." + boardType);
        populateInterfaceFromJson(boardIface.get(), boardValues, objServer);
        auto exposes = boardValues.find("exposes");
        if (exposes == boardValues.end())
        {
            continue;
        }
        for (auto &item : *exposes)
        {
            auto findName = item.find("name");
            if (findName == item.end())
            {
                std::cerr << "cannot find name in field " << item << "\n";
                continue;
            }
            auto findStatus = item.find("status");
            // if status is not found it is assumed to be status = 'okay'
            if (findStatus != item.end())
            {
                if (*findStatus == "disabled")
                {
                    continue;
                }
            }
            auto findType = item.find("type");
            std::string itemType;
            if (findType != item.end())
            {
                itemType = findType->get<std::string>();
                std::regex_replace(itemType.begin(), itemType.begin(),
                                   itemType.end(), ILLEGAL_DBUS_REGEX, "_");
            }
            else
            {
                itemType = "unknown";
            }
            std::string itemName = findName->get<std::string>();
            std::regex_replace(itemName.begin(), itemName.begin(),
                               itemName.end(), ILLEGAL_DBUS_REGEX, "_");
            auto itemObject = objServer.add_object(boardName + "/" + itemName);
            auto itemIface = itemObject->add_interface(
                "xyz.openbmc_project.Configuration." + itemType);

            populateInterfaceFromJson(itemIface.get(), item, objServer);

            for (auto &objectPair : nlohmann::json::iterator_wrapper(item))
            {
                if (objectPair.value().type() ==
                    nlohmann::json::value_t::object)
                {
                    auto objectIface = itemObject->add_interface(
                        "xyz.openbmc_project.Configuration." + itemType + "." +
                        objectPair.key());
                    populateInterfaceFromJson(objectIface.get(),
                                              objectPair.value(), objServer);
                }
                else if (objectPair.value().type() ==
                         nlohmann::json::value_t::array)
                {
                    size_t index = 0;
                    for (auto &arrayItem : objectPair.value())
                    {
                        if (arrayItem.type() != nlohmann::json::value_t::object)
                        {
                            std::cerr << "dbus format error" << arrayItem
                                      << "\n";
                            break;
                        }
                        auto objectIface = itemObject->add_interface(
                            "xyz.openbmc_project.Configuration." + itemType +
                            "." + objectPair.key() + "." +
                            std::to_string(index));
                        index++;
                        populateInterfaceFromJson(objectIface.get(), arrayItem,
                                                  objServer);
                    }
                }
            }
        }
    }
}

// finds the template character (currently set to $) and replaces the value with
// the field found in a dbus object i.e. $ADDRESS would get populated with the
// ADDRESS field from a object on dbus
void templateCharReplace(
    nlohmann::json::iterator &keyPair,
    const boost::container::flat_map<std::string, dbus::dbus_variant>
        &foundDevice,
    size_t &foundDeviceIdx)
{
    if (keyPair.value().type() != nlohmann::json::value_t::string)
    {
        return;
    }

    std::string value = keyPair.value();
    if (value.find(TEMPLATE_CHAR) != std::string::npos)
    {
        std::string templateValue = value;

        templateValue.erase(0, 1); // remove template character

        // special case index
        if ("index" == templateValue)
        {
            keyPair.value() = foundDeviceIdx;
        }
        else
        {
            std::string subsitute;
            for (auto &foundDevicePair : foundDevice)
            {
                if (boost::iequals(foundDevicePair.first, templateValue))
                {
                    // convert value to string
                    // respresentation
                    subsitute = boost::apply_visitor(
                        [](const auto &x) {
                            return boost::lexical_cast<std::string>(x);
                        },
                        foundDevicePair.second);
                    break;
                }
            }
            if (!subsitute.size())
            {
                std::cerr << "could not find symbol " << templateValue << "\n";
            }
            else
            {
                keyPair.value() = subsitute;
            }
        }
    }
}

bool findJsonFiles(std::vector<nlohmann::json> &configurations)
{
    // find configuration files
    std::vector<fs::path> jsonPaths;
    if (!find_files(fs::path(CONFIGURATION_DIR), R"(.*\.json)", jsonPaths, 0))
    {
        std::cerr << "Unable to find any configuration files in "
                  << CONFIGURATION_DIR << "\n";
        return false;
    }
    for (auto &jsonPath : jsonPaths)
    {
        std::ifstream jsonStream(jsonPath.c_str());
        if (!jsonStream.good())
        {
            std::cerr << "unable to open " << jsonPath.string() << "\n";
            continue;
        }
        auto data = nlohmann::json::parse(jsonStream, nullptr, false);
        if (data.is_discarded())
        {
            std::cerr << "syntax error in " << jsonPath.string() << "\n";
            continue;
        }
        if (data.type() == nlohmann::json::value_t::array)
        {
            for (auto &d : data)
            {
                configurations.emplace_back(d);
            }
        }
        else
        {
            configurations.emplace_back(data);
        }
    }
}

bool rescan(nlohmann::json &systemConfiguration)
{
    std::vector<nlohmann::json> configurations;
    if (!findJsonFiles(configurations))
    {
        false;
    }
    // preprocess already passed configurations and missing fields
    if (systemConfiguration.size())
    {
        for (auto it = configurations.begin(); it != configurations.end();)
        {
            auto findName = it->find("name");
            if (findName == it->end())
            {
                std::cerr << "configuration missing name field " << *it << "\n";
                it = configurations.erase(it);
                continue;
            }
            else if (findName->type() != nlohmann::json::value_t::string)
            {
                std::cerr << "name field must be a string " << *findName
                          << "\n";
                it = configurations.erase(it);
                continue;
            }
            auto findAlreadyFound =
                systemConfiguration.find(findName->get<std::string>());
            if (findAlreadyFound != systemConfiguration.end())
            {
                it = configurations.erase(it);
                continue;
            }
            // TODO: add in tags to determine if configuration should be
            // refreshed on AC / DC / Always.
            it++;
        }
    }

    // probe until no probes pass
    bool probePassed = true;
    while (probePassed)
    {
        probePassed = false;
        for (auto it = configurations.begin(); it != configurations.end();)
        {
            bool eraseConfig = false;
            auto findProbe = it->find("probe");
            auto findName = it->find("name");

            nlohmann::json probeCommand;
            // check for poorly formatted fields, probe must be an array
            if (findProbe == it->end())
            {
                std::cerr << "configuration file missing probe:\n " << *it
                          << "\n";
                eraseConfig = true;
            }
            else if ((*findProbe).type() != nlohmann::json::value_t::array)
            {
                probeCommand = nlohmann::json::array();
                probeCommand.push_back(*findProbe);
            }
            else
            {
                probeCommand = *findProbe;
            }

            if (findName == it->end())
            {
                std::cerr << "configuration file missing name:\n " << *it
                          << "\n";
                eraseConfig = true;
            }

            std::vector<
                boost::container::flat_map<std::string, dbus::dbus_variant>>
                foundDevices;
            if (!eraseConfig && probe(probeCommand, foundDevices))
            {
                eraseConfig = true;
                probePassed = true;
                std::string name = *findName;
                PASSED_PROBES.push_back(name);

                size_t foundDeviceIdx = 0;

                for (auto &foundDevice : foundDevices)
                {
                    for (auto keyPair = it->begin(); keyPair != it->end();
                         keyPair++)
                    {
                        templateCharReplace(keyPair, foundDevice,
                                            foundDeviceIdx);
                    }
                    auto findExpose = it->find("exposes");
                    if (findExpose == it->end())
                    {
                        continue;
                    }
                    for (auto &expose : *findExpose)
                    {
                        for (auto keyPair = expose.begin();
                             keyPair != expose.end(); keyPair++)
                        {

                            // fill in template characters with devices
                            // found
                            templateCharReplace(keyPair, foundDevice,
                                                foundDeviceIdx);
                            // special case bind
                            if (boost::starts_with(keyPair.key(), "bind_"))
                            {
                                if (keyPair.value().type() !=
                                    nlohmann::json::value_t::string)
                                {
                                    std::cerr
                                        << "bind_ value must be of type string "
                                        << keyPair.key() << "\n";
                                    continue;
                                }
                                bool foundBind = false;
                                std::string bind =
                                    keyPair.key().substr(sizeof("bind_") - 1);
                                for (auto &configurationPair :
                                     nlohmann::json::iterator_wrapper(
                                         systemConfiguration))
                                {

                                    auto configListFind =
                                        configurationPair.value().find(
                                            "exposes");

                                    if (configListFind ==
                                            configurationPair.value().end() ||
                                        configListFind->type() !=
                                            nlohmann::json::value_t::array)
                                    {
                                        continue;
                                    }
                                    for (auto &exposedObject : *configListFind)
                                    {
                                        std::string foundObjectName =
                                            (exposedObject)["name"];
                                        if (boost::iequals(
                                                foundObjectName,
                                                keyPair.value()
                                                    .get<std::string>()))
                                        {
                                            exposedObject["status"] = "okay";
                                            expose[bind] = exposedObject;

                                            foundBind = true;
                                            break;
                                        }
                                    }
                                    if (foundBind)
                                    {
                                        break;
                                    }
                                }
                                if (!foundBind)
                                {
                                    std::cerr << "configuration file "
                                                 "dependency error, "
                                                 "could not find bind "
                                              << keyPair.value() << "\n";
                                }
                            }
                        }
                    }
                }
                systemConfiguration[name] = (*it);
                foundDeviceIdx++;
            }

            if (eraseConfig)
            {
                it = configurations.erase(it);
            }
            else
            {
                it++;
            }
        }
    }
}

void propertiesChangedCallback(
    std::vector<std::pair<std::unique_ptr<dbus::match>,
                          std::shared_ptr<dbus::filter>>> &dbusMatches,
    nlohmann::json &systemConfiguration, dbus::DbusObjectServer &objServer,
    std::shared_ptr<dbus::filter> dbusFilter)
{
    static std::future<void> future;
    static std::atomic_bool threadRunning(false);
    static std::atomic_bool pendingCallback(false);
    bool notRunning = false;
    if (threadRunning.compare_exchange_strong(notRunning, true))
    {
        future = std::async(std::launch::async, [&] {

            do
            {
                std::this_thread::sleep_for(std::chrono::seconds(
                    SLEEP_AFTER_PROPERTIES_CHANGE_SECONDS));
                auto oldConfiguration = systemConfiguration;
                DBUS_PROBE_OBJECTS.clear();
                pendingCallback = false;
                rescan(systemConfiguration);
                auto newConfiguration = systemConfiguration;
                for (auto it = newConfiguration.begin();
                     it != newConfiguration.end();)
                {
                    auto findKey = oldConfiguration.find(it.key());
                    if (findKey != oldConfiguration.end())
                    {
                        it = newConfiguration.erase(it);
                    }
                    else
                    {
                        it++;
                    }
                }

                registerCallbacks(dbusMatches, systemConfiguration, objServer);
                // todo: for now, only add new configurations, unload to come
                // later
                // unloadOverlays();
                loadOverlays(newConfiguration);
                // this line to be removed in future
                writeJsonFiles(systemConfiguration);
                // only post new items to bus for now
                postToDbus(newConfiguration, objServer);
            } while (pendingCallback);
            threadRunning = false;
        });
    }
    else
    {
        pendingCallback = true;
    }
    if (dbusFilter != nullptr)
    {
        dbusFilter->async_dispatch([&, dbusFilter](boost::system::error_code ec,
                                                   dbus::message) {
            if (ec)
            {
                std::cerr << "properties changed callback error " << ec << "\n";
            }
            propertiesChangedCallback(dbusMatches, systemConfiguration,
                                      objServer, dbusFilter);
        });
    }
}

void registerCallbacks(
    std::vector<std::pair<std::unique_ptr<dbus::match>,
                          std::shared_ptr<dbus::filter>>> &dbusMatches,
    nlohmann::json &systemConfiguration, dbus::DbusObjectServer &objServer)
{
    static boost::container::flat_set<std::string> watchedObjects;

    for (const auto &objectMap : DBUS_PROBE_OBJECTS)
    {
        auto findObject = watchedObjects.find(objectMap.first);
        if (findObject != watchedObjects.end())
        {
            continue;
        }
        // this creates a filter for properties changed for any new probe type
        auto propertyChange = std::make_unique<dbus::match>(
            SYSTEM_BUS,
            "type='signal',member='PropertiesChanged',arg0='" +
                objectMap.first + "'");
        auto filter =
            std::make_shared<dbus::filter>(SYSTEM_BUS, [](dbus::message &m) {
                auto member = m.get_member();
                return member == "PropertiesChanged";
            });

        filter->async_dispatch([&, filter](boost::system::error_code ec,
                                           dbus::message) {
            if (ec)
            {
                std::cerr << "register callbacks callback error " << ec << "\n";
            }
            propertiesChangedCallback(dbusMatches, systemConfiguration,
                                      objServer, filter);
        });
        dbusMatches.emplace_back(std::move(propertyChange), filter);
    }
}

int main(int argc, char **argv)
{
    // setup connection to dbus
    boost::asio::io_service io;
    SYSTEM_BUS = std::make_shared<dbus::connection>(io, dbus::bus::system);

    dbus::DbusObjectServer objServer(SYSTEM_BUS);
    SYSTEM_BUS->request_name("xyz.openbmc_project.EntityManager");
    std::vector<
        std::pair<std::unique_ptr<dbus::match>, std::shared_ptr<dbus::filter>>>
        dbusMatches;

    nlohmann::json systemConfiguration = nlohmann::json::object();
    auto iface = std::make_shared<dbus::DbusInterface>(
        "xyz.openbmc_project.EntityManager", SYSTEM_BUS);
    io.post([&]() {
        unloadAllOverlays();
        propertiesChangedCallback(dbusMatches, systemConfiguration, objServer,
                                  nullptr);
        auto object = std::make_shared<dbus::DbusObject>(
            SYSTEM_BUS, "/xyz/openbmc_project/EntityManager");
        objServer.register_object(object);

        object->register_interface(iface);

    });

    // to keep reference to the match / filter objects so they don't get
    // destroyed

    iface->register_method("ReScan", [&]() {
        propertiesChangedCallback(dbusMatches, systemConfiguration, objServer,
                                  nullptr);
        return std::tuple<>(); // this is a bug in boost-dbus, needs some sort
                               // of return
    });

    io.run();

    return 0;
}
