/**
 * Copyright © 2017 IBM 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 "utility.hpp"

#include "types.hpp"

#include <fstream>

namespace phosphor
{
namespace power
{
namespace util
{

constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";

constexpr auto DECORATOR_CHASSIS_ID =
    "xyz.openbmc_project.Inventory.Decorator.Slot";
constexpr auto CHASSIS_ID_PROPERTY = "SlotNumber";

using json = nlohmann::json;

std::string getService(const std::string& path, const std::string& interface,
                       sdbusplus::bus_t& bus, bool logError)
{
    auto method = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
                                      MAPPER_INTERFACE, "GetObject");

    method.append(path);
    method.append(std::vector<std::string>({interface}));

    auto reply = bus.call(method);

    auto response =
        reply.unpack<std::map<std::string, std::vector<std::string>>>();

    if (response.empty())
    {
        if (logError)
        {
            lg2::error("Error in mapper response for getting service name "
                       "PATH={PATH} INTERFACE={INTERFACE}",
                       "PATH", path, "INTERFACE", interface);
        }
        return std::string{};
    }

    return response.begin()->first;
}

DbusPropertyMap getAllProperties(sdbusplus::bus_t& bus, const std::string& path,
                                 const std::string& interface,
                                 const std::string& service)
{
    DbusPropertyMap properties;

    auto serviceStr = service;
    if (serviceStr.empty())
    {
        serviceStr = getService(path, interface, bus);
        if (serviceStr.empty())
        {
            return properties;
        }
    }

    auto method = bus.new_method_call(serviceStr.c_str(), path.c_str(),
                                      PROPERTY_INTF, "GetAll");
    method.append(interface);
    auto reply = bus.call(method);
    reply.read(properties);
    return properties;
}

DbusSubtree getSubTree(sdbusplus::bus_t& bus, const std::string& path,
                       const std::string& interface, int32_t depth)
{
    return getSubTree(bus, path, std::vector<std::string>({interface}), depth);
}

DbusSubtree getSubTree(sdbusplus::bus_t& bus, const std::string& path,
                       const std::vector<std::string>& interfaces,
                       int32_t depth)
{
    auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
                                          MAPPER_INTERFACE, "GetSubTree");
    mapperCall.append(path);
    mapperCall.append(depth);
    mapperCall.append(interfaces);

    auto reply = bus.call(mapperCall);

    auto response = reply.unpack<DbusSubtree>();

    return response;
}

std::vector<DbusPath> getAssociatedSubTreePaths(
    sdbusplus::bus_t& bus,
    const sdbusplus::message::object_path& associationPath,
    const sdbusplus::message::object_path& path,
    const std::vector<std::string>& interfaces, int32_t depth)
{
    auto mapperCall =
        bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE,
                            "GetAssociatedSubTreePaths");
    mapperCall.append(associationPath);
    mapperCall.append(path);
    mapperCall.append(depth);
    mapperCall.append(interfaces);

    auto reply = bus.call(mapperCall);

    auto response = reply.unpack<std::vector<DbusPath>>();

    return response;
}

json loadJSONFromFile(const char* path)
{
    std::ifstream ifs(path);
    if (!ifs.good())
    {
        lg2::error("Unable to open file PATH={PATH}", "PATH", path);
        return nullptr;
    }
    auto data = json::parse(ifs, nullptr, false);
    if (data.is_discarded())
    {
        lg2::error("Failed to parse json PATH={PATH}", "PATH", path);
        return nullptr;
    }
    return data;
}

phosphor::pmbus::Type getPMBusAccessType(const json& json)
{
    using namespace phosphor::pmbus;
    Type type;

    auto typeStr = json.at("inventoryPMBusAccessType");

    if (typeStr == "Hwmon")
    {
        type = Type::Hwmon;
    }
    else if (typeStr == "DeviceDebug")
    {
        type = Type::DeviceDebug;
    }
    else if (typeStr == "Debug")
    {
        type = Type::Debug;
    }
    else if (typeStr == "HwmonDeviceDebug")
    {
        type = Type::HwmonDeviceDebug;
    }
    else
    {
        type = Type::Base;
    }
    return type;
}

bool isPoweredOn(sdbusplus::bus_t& bus, bool defaultState)
{
    int32_t state = defaultState;

    try
    {
        // When state = 1, system is powered on
        auto service = util::getService(POWER_OBJ_PATH, POWER_IFACE, bus);
        getProperty<int32_t>(POWER_IFACE, "state", POWER_OBJ_PATH, service, bus,
                             state);
    }
    catch (const std::exception& e)
    {
        lg2::info("Failed to get power state.");
    }
    return state != 0;
}

std::vector<std::string> getPSUInventoryPaths(sdbusplus::bus_t& bus)
{
    std::vector<std::string> paths;
    auto method = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
                                      MAPPER_INTERFACE, "GetSubTreePaths");
    method.append(INVENTORY_OBJ_PATH);
    method.append(0); // Depth 0 to search all
    method.append(std::vector<std::string>({PSU_INVENTORY_IFACE}));
    auto reply = bus.call(method);

    reply.read(paths);
    return paths;
}

std::vector<std::string> getChassisInventoryPaths(sdbusplus::bus_t& bus)
{
    std::vector<std::string> paths;
    auto method = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
                                      MAPPER_INTERFACE, "GetSubTreePaths");
    method.append(INVENTORY_OBJ_PATH);
    method.append(0); // Depth 0 to search all
    method.append(std::vector<std::string>({CHASSIS_IFACE}));
    auto reply = bus.call(method);

    reply.read(paths);
    return paths;
}

uint64_t getChassisInventoryUniqueId(sdbusplus::bus_t& bus,
                                     const std::string& path)
{
    uint32_t chassisId;
    getProperty(DECORATOR_CHASSIS_ID, CHASSIS_ID_PROPERTY, path,
                INVENTORY_MGR_IFACE, bus, chassisId);
    return static_cast<uint64_t>(chassisId);
}

uint64_t getParentEMUniqueId(sdbusplus::bus_t& bus, const std::string& path)
{
    namespace fs = std::filesystem;
    uint64_t chassisId;
    fs::path fspath(path);
    getProperty(DECORATOR_CHASSIS_ID, CHASSIS_ID_PROPERTY, fspath.parent_path(),
                ENTITY_MGR_SERVICE, bus, chassisId);
    return chassisId;
}

} // namespace util
} // namespace power
} // namespace phosphor
