/*
// Copyright (c) 2019 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 "types.hpp"

#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/asio/post.hpp>
#include <boost/container/flat_set.hpp>
#include <cold_redundancy.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/asio/sd_event.hpp>
#include <sdbusplus/bus/match.hpp>

#include <array>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <regex>

namespace
{
constexpr const std::array<const char*, 1> psuInterfaceTypes = {
    "xyz.openbmc_project.Configuration.pmbus"};
std::string inventoryPath = std::string(INVENTORY_OBJ_PATH) + "/system";
const constexpr char* eventPath = "/xyz/openbmc_project/State/Decorator";
std::vector<std::unique_ptr<PowerSupply>> powerSupplies;
} // namespace

ColdRedundancy::ColdRedundancy(
    boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
    std::shared_ptr<sdbusplus::asio::connection>& systemBus) :
    filterTimer(io),
    systemBus(systemBus)
{
    post(io,
         [this, &io, &objectServer, &systemBus]() { createPSU(systemBus); });
    std::function<void(sdbusplus::message_t&)> eventHandler =
        [this, &io, &objectServer, &systemBus](sdbusplus::message_t& message) {
            if (message.is_method_error())
            {
                std::cerr << "callback method error\n";
                return;
            }
            filterTimer.expires_after(std::chrono::seconds(1));
            filterTimer.async_wait([this, &io, &objectServer, &systemBus](
                                       const boost::system::error_code& ec) {
                if (ec == boost::asio::error::operation_aborted)
                {
                    return;
                }
                else if (ec)
                {
                    std::cerr << "timer error\n";
                }
                createPSU(systemBus);
            });
        };

    std::function<void(sdbusplus::message_t&)> eventCollect =
        [&](sdbusplus::message_t& message) {
            std::string objectName;
            boost::container::flat_map<std::string, std::variant<bool>> values;
            std::string path = message.get_path();
            std::size_t slantingPos = path.find_last_of("/\\");
            if ((slantingPos == std::string::npos) ||
                ((slantingPos + 1) >= path.size()))
            {
                std::cerr << "Unable to get PSU state name from path\n";
                return;
            }
            std::string statePSUName = path.substr(slantingPos + 1);

            std::size_t hypenPos = statePSUName.find("_");
            if (hypenPos == std::string::npos)
            {
                std::cerr << "Unable to get PSU name from PSU path\n";
                return;
            }
            std::string psuName = statePSUName.substr(0, hypenPos);

            try
            {
                message.read(objectName, values);
            }
            catch (const sdbusplus::exception_t& e)
            {
                std::cerr << "Failed to read message from PSU Event\n";
                return;
            }

            for (auto& psu : powerSupplies)
            {
                if (psu->name != psuName)
                {
                    continue;
                }

                std::string psuEventName = "functional";
                auto findEvent = values.find(psuEventName);
                if (findEvent != values.end())
                {
                    bool* functional = std::get_if<bool>(&(findEvent->second));
                    if (functional == nullptr)
                    {
                        std::cerr << "Unable to get valid functional status\n";
                        continue;
                    }
                    if (*functional)
                    {
                        psu->state = CR::PSUState::normal;
                    }
                    else
                    {
                        psu->state = CR::PSUState::acLost;
                    }
                }
            }
        };

    using namespace sdbusplus::bus::match::rules;
    for (const char* type : psuInterfaceTypes)
    {
        auto match = std::make_unique<sdbusplus::bus::match_t>(
            static_cast<sdbusplus::bus_t&>(*systemBus),
            type::signal() + member("PropertiesChanged") +
                path_namespace(inventoryPath) + arg0namespace(type),
            eventHandler);
        matches.emplace_back(std::move(match));
    }

    for (const char* eventType : psuEventInterface)
    {
        auto eventMatch = std::make_unique<sdbusplus::bus::match_t>(
            static_cast<sdbusplus::bus_t&>(*systemBus),
            type::signal() + member("PropertiesChanged") +
                path_namespace(eventPath) + arg0namespace(eventType),
            eventCollect);
        matches.emplace_back(std::move(eventMatch));
    }
}

static const constexpr int psuDepth = 3;
// Check PSU information from entity-manager D-Bus interface and use the bus
// address to create PSU Class for cold redundancy.
void ColdRedundancy::createPSU(
    std::shared_ptr<sdbusplus::asio::connection>& conn)
{
    numberOfPSU = 0;
    powerSupplies.clear();

    // call mapper to get matched obj paths
    conn->async_method_call(
        [this, &conn](const boost::system::error_code ec,
                      CR::GetSubTreeType subtree) {
            if (ec)
            {
                std::cerr << "Exception happened when communicating to "
                             "ObjectMapper\n";
                return;
            }
            for (const auto& object : subtree)
            {
                std::string pathName = object.first;
                for (const auto& serviceIface : object.second)
                {
                    std::string serviceName = serviceIface.first;
                    for (const auto& interface : serviceIface.second)
                    {
                        // only get property of matched interface
                        bool isIfaceMatched = false;
                        for (const auto& type : psuInterfaceTypes)
                        {
                            if (type == interface)
                            {
                                isIfaceMatched = true;
                                break;
                            }
                        }
                        if (!isIfaceMatched)
                            continue;

                        conn->async_method_call(
                            [this, &conn,
                             interface](const boost::system::error_code ec,
                                        CR::PropertyMapType propMap) {
                                if (ec)
                                {
                                    std::cerr
                                        << "Exception happened when get all "
                                           "properties\n";
                                    return;
                                }

                                auto configName =
                                    std::get_if<std::string>(&propMap["Name"]);
                                if (configName == nullptr)
                                {
                                    std::cerr << "error finding necessary "
                                                 "entry in configuration\n";
                                    return;
                                }

                                auto configBus =
                                    std::get_if<uint64_t>(&propMap["Bus"]);
                                auto configAddress =
                                    std::get_if<uint64_t>(&propMap["Address"]);

                                if (configBus == nullptr ||
                                    configAddress == nullptr)
                                {
                                    std::cerr << "error finding necessary "
                                                 "entry in configuration\n";
                                    return;
                                }
                                for (auto& psu : powerSupplies)
                                {
                                    if ((static_cast<uint8_t>(*configBus) ==
                                         psu->bus) &&
                                        (static_cast<uint8_t>(*configAddress) ==
                                         psu->address))
                                    {
                                        return;
                                    }
                                }

                                uint8_t order = 0;

                                powerSupplies.emplace_back(
                                    std::make_unique<PowerSupply>(
                                        *configName,
                                        static_cast<uint8_t>(*configBus),
                                        static_cast<uint8_t>(*configAddress),
                                        order, conn));

                                numberOfPSU++;
                                std::vector<uint8_t> orders = {};
                                for (auto& psu : powerSupplies)
                                {
                                    orders.push_back(psu->order);
                                }
                            },
                            serviceName.c_str(), pathName.c_str(),
                            "org.freedesktop.DBus.Properties", "GetAll",
                            interface);
                    }
                }
            }
        },
        "xyz.openbmc_project.ObjectMapper",
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper", "GetSubTree",
        "/xyz/openbmc_project/inventory/system", psuDepth, psuInterfaceTypes);
}

PowerSupply::PowerSupply(
    std::string& name, uint8_t bus, uint8_t address, uint8_t order,
    const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection) :
    name(name),
    bus(bus), address(address), order(order)
{
    CR::getPSUEvent(dbusConnection, name, state);
}
