/*
// Copyright (c) 2017 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 <boost/algorithm/string/predicate.hpp>
#include <experimental/filesystem>
#include <fstream>
#include <regex>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/bus/match.hpp>

namespace fs = std::experimental::filesystem;
const static constexpr char* POWER_INTERFACE_NAME =
    "xyz.openbmc_project.Chassis.Control.Power";
const static constexpr char* POWER_OBJECT_NAME =
    "/xyz/openbmc_project/Chassis/Control/Power0";

bool getSensorConfiguration(
    const std::string& type,
    const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
    ManagedObjectType& resp, bool useCache)
{
    static ManagedObjectType managedObj;

    if (!useCache)
    {
        managedObj.clear();
        sdbusplus::message::message getManagedObjects =
            dbusConnection->new_method_call(
                ENTITY_MANAGER_NAME, "/", "org.freedesktop.DBus.ObjectManager",
                "GetManagedObjects");
        bool err = false;
        try
        {
            sdbusplus::message::message reply =
                dbusConnection->call(getManagedObjects);
            err = reply.is_method_error();
            if (!err)
            {
                reply.read(managedObj);
            }
        }
        catch (const sdbusplus::exception::exception&)
        {
            err = true;
        }

        if (err)
        {
            std::cerr << "Error communicating to entity manager\n";
            return false;
        }
    }
    for (const auto& pathPair : managedObj)
    {
        std::vector<boost::container::flat_map<std::string, BasicVariantType>>
            sensorData;
        bool correctType = false;
        for (const auto& entry : pathPair.second)
        {
            if (boost::starts_with(entry.first, type))
            {
                correctType = true;
                break;
            }
        }
        if (correctType)
        {
            resp.emplace(pathPair);
        }
    }
    return true;
}

bool find_files(const fs::path dir_path, const std::string& match_string,
                std::vector<fs::path>& found_paths, unsigned int symlink_depth)
{
    if (!fs::exists(dir_path))
        return false;

    fs::directory_iterator end_itr;
    std::regex search(match_string);
    std::smatch match;
    for (auto& p : fs::recursive_directory_iterator(dir_path))
    {
        std::string path = p.path().string();
        if (!is_directory(p))
        {
            if (std::regex_search(path, match, search))
                found_paths.emplace_back(p.path());
        }
        // since we're using a recursive iterator, these should only be symlink
        // dirs
        else if (symlink_depth)
        {
            find_files(p.path(), match_string, found_paths, symlink_depth - 1);
        }
    }
    return true;
}

// initially returns false, then sets up matches and returns status
// should be called once first to initialize
bool isPowerOn(const std::shared_ptr<sdbusplus::asio::connection>& conn)
{
    static std::unique_ptr<sdbusplus::bus::match::match> powerMatch = nullptr;
    static bool powerStatusOn = false;

    if (powerMatch != nullptr)
    {
        return powerStatusOn;
    }

    // create a match for powergood changes, first time do a method call to
    // return the correct value
    std::function<void(sdbusplus::message::message & message)> eventHandler =
        [&powerStatusOn](sdbusplus::message::message& message) {
            std::string objectName;
            boost::container::flat_map<std::string,
                                       sdbusplus::message::variant<int32_t>>
                values;
            message.read(objectName, values);
            auto findPgood = values.find("pgood");
            if (findPgood != values.end())
            {
                powerStatusOn = sdbusplus::message::variant_ns::get<int32_t>(
                    findPgood->second);
            }
        };

    powerMatch = std::make_unique<sdbusplus::bus::match::match>(
        static_cast<sdbusplus::bus::bus&>(*conn),
        "type='signal',interface='org.freedesktop.DBus.Properties',path_"
        "namespace='/xyz/openbmc_project/Chassis/Control/"
        "power0',arg0='xyz.openbmc_project.Chassis.Control.Power'",
        eventHandler);

    conn->async_method_call(
        [&powerStatusOn](boost::system::error_code ec,
                         const sdbusplus::message::variant<int32_t>& pgood) {
            if (ec)
            {
                std::cerr << "Error getting initial power status\n";
                return;
            }
            powerStatusOn = sdbusplus::message::variant_ns::get<int32_t>(pgood);
        },
        POWER_INTERFACE_NAME, POWER_OBJECT_NAME,
        "org.freedesktop.DBus.Properties", "Get", "pgood");

    return powerStatusOn;
}