/*
// 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.
*/
#pragma once

#include "app.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "openbmc_dbus_rest.hpp"
#include "query.hpp"
#include "redfish_util.hpp"
#include "registries/privilege_registry.hpp"
#include "utils/json_utils.hpp"
#include "utils/stl_utils.hpp"

#include <boost/system/error_code.hpp>
#include <sdbusplus/asio/property.hpp>

#include <array>
#include <optional>
#include <string_view>
#include <variant>

#include "managed_store.hpp"

#ifdef UNIT_TEST_BUILD
#include "test/g3/mock_managed_store.hpp" // NOLINT
#endif

namespace redfish
{

void getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp);
std::string getHostName();

static constexpr std::string_view sshServiceName = "dropbear";
static constexpr std::string_view httpsServiceName = "bmcweb";
static constexpr std::string_view ipmiServiceName = "phosphor-ipmi-net";

// Mapping from Redfish NetworkProtocol key name to backend service that hosts
// that protocol.
static constexpr std::array<std::pair<std::string_view, std::string_view>, 3>
    networkProtocolToDbus = {{{"SSH", sshServiceName},
                              {"HTTPS", httpsServiceName},
                              {"IPMI", ipmiServiceName}}};

inline void extractNTPServersAndDomainNamesData(
    const dbus::utility::ManagedObjectType& dbusData,
    std::vector<std::string>& ntpData, std::vector<std::string>& dnData)
{
    for (const auto& obj : dbusData)
    {
        for (const auto& ifacePair : obj.second)
        {
            if (ifacePair.first !=
                "xyz.openbmc_project.Network.EthernetInterface")
            {
                continue;
            }

            for (const auto& propertyPair : ifacePair.second)
            {
                if (propertyPair.first == "StaticNTPServers")
                {
                    const std::vector<std::string>* ntpServers =
                        std::get_if<std::vector<std::string>>(
                            &propertyPair.second);
                    if (ntpServers != nullptr)
                    {
                        ntpData.insert(ntpData.end(), ntpServers->begin(),
                                       ntpServers->end());
                    }
                }
                else if (propertyPair.first == "DomainName")
                {
                    const std::vector<std::string>* domainNames =
                        std::get_if<std::vector<std::string>>(
                            &propertyPair.second);
                    if (domainNames != nullptr)
                    {
                        dnData.insert(dnData.end(), domainNames->begin(),
                                      domainNames->end());
                    }
                }
            }
        }
    }
    stl_utils::removeDuplicate(ntpData);
    stl_utils::removeDuplicate(dnData);
}

template <typename CallbackFunc>
void getEthernetIfaceData(
    const managedStore::ManagedObjectStoreContext& context,
    CallbackFunc&& callback)
{
    managedStore::GetManagedObjectStore()->getManagedObjectsWithContext(
        "xyz.openbmc_project.Network", {"/xyz/openbmc_project/network"},
        context,
        [callback{std::forward<CallbackFunc>(callback)}](
            const boost::system::error_code& errorCode,
            const dbus::utility::ManagedObjectType& dbusData) {
        std::vector<std::string> ntpServers;
        std::vector<std::string> domainNames;

        if (errorCode)
        {
            callback(false, ntpServers, domainNames);
            return;
        }

        extractNTPServersAndDomainNamesData(dbusData, ntpServers, domainNames);

        callback(true, ntpServers, domainNames);
        });
}

inline void afterNetworkPortRequest(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const boost::system::error_code& ec,
    const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
{
    if (ec)
    {
        messages::internalError(asyncResp->res);
        return;
    }

    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    for (const auto& data : socketData)
    {
        const std::string& socketPath = get<0>(data);
        const std::string& protocolName = get<1>(data);
        bool isProtocolEnabled = get<2>(data);

        asyncResp->res.jsonValue[protocolName]["ProtocolEnabled"] =
            isProtocolEnabled;
        asyncResp->res.jsonValue[protocolName]["Port"] = nullptr;
        getPortNumber(
            socketPath, requestContext,
            [asyncResp, protocolName](const boost::system::error_code& ec2,
                                      int portNumber) {
            if (ec2)
            {
                messages::internalError(asyncResp->res);
                return;
            }
            asyncResp->res.jsonValue[protocolName]["Port"] = portNumber;
            });
    }
}

inline void getNetworkData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                           const crow::Request& req)
{
    asyncResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/NetworkProtocol.json>; rel=describedby");
    asyncResp->res.jsonValue["@odata.type"] =
        "#ManagerNetworkProtocol.v1_5_0.ManagerNetworkProtocol";
    asyncResp->res.jsonValue["@odata.id"] =
        "/redfish/v1/Managers/bmc/NetworkProtocol";
    asyncResp->res.jsonValue["Id"] = "NetworkProtocol";
    asyncResp->res.jsonValue["Name"] = "Manager Network Protocol";
    asyncResp->res.jsonValue["Description"] = "Manager Network Service";
    asyncResp->res.jsonValue["Status"]["Health"] = "OK";
    asyncResp->res.jsonValue["Status"]["HealthRollup"] = "OK";
    asyncResp->res.jsonValue["Status"]["State"] = "Enabled";

    // HTTP is Mandatory attribute as per OCP Baseline Profile - v1.0.0,
    // but from security perspective it is not recommended to use.
    // Hence using protocolEnabled as false to make it OCP and security-wise
    // compliant
    asyncResp->res.jsonValue["HTTP"]["Port"] = nullptr;
    asyncResp->res.jsonValue["HTTP"]["ProtocolEnabled"] = false;

    std::string hostName = getHostName();

    asyncResp->res.jsonValue["HostName"] = hostName;

    getNTPProtocolEnabled(asyncResp);

    managedStore::ManagedObjectStoreContext context(asyncResp);
    getEthernetIfaceData(
        context,
        [hostName, asyncResp](const bool& success,
                              const std::vector<std::string>& ntpServers,
                              const std::vector<std::string>& domainNames) {
        if (!success)
        {
            messages::resourceNotFound(asyncResp->res, "ManagerNetworkProtocol",
                                       "NetworkProtocol");
            return;
        }
        asyncResp->res.jsonValue["NTP"]["NTPServers"] = ntpServers;
        if (!hostName.empty())
        {
            std::string fqdn = hostName;
            if (!domainNames.empty())
            {
                fqdn += ".";
                fqdn += domainNames[0];
            }
            asyncResp->res.jsonValue["FQDN"] = std::move(fqdn);
        }
        });

    Privileges effectiveUserPrivileges =
        redfish::getUserPrivileges(req.userRole);

    // /redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates is
    // something only ConfigureManager can access then only display when
    // the user has permissions ConfigureManager
    if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
                                         effectiveUserPrivileges))
    {
        asyncResp->res.jsonValue["HTTPS"]["Certificates"]["@odata.id"] =
            "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates";
    }

    getPortStatusAndPath(std::span(networkProtocolToDbus), context,
                         std::bind_front(afterNetworkPortRequest, asyncResp));
} // namespace redfish

inline void handleNTPProtocolEnabled(
    const bool& ntpEnabled, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    std::string timeSyncMethod;
    if (ntpEnabled)
    {
        timeSyncMethod = "xyz.openbmc_project.Time.Synchronization.Method.NTP";
    }
    else
    {
        timeSyncMethod =
            "xyz.openbmc_project.Time.Synchronization.Method.Manual";
    }

    managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
        asyncResp->strand_,
        [asyncResp](const boost::system::error_code& errorCode) {
        if (errorCode)
        {
            messages::internalError(asyncResp->res);
        }
        },
        "xyz.openbmc_project.Settings", "/xyz/openbmc_project/time/sync_method",
        "org.freedesktop.DBus.Properties", "Set",
        "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod",
        dbus::utility::DbusVariantType{timeSyncMethod});
}

inline void
    handleNTPServersPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                          const std::vector<nlohmann::json>& ntpServerObjects,
                          std::vector<std::string> currentNtpServers)
{
    std::vector<std::string>::iterator currentNtpServer =
        currentNtpServers.begin();
    for (size_t index = 0; index < ntpServerObjects.size(); index++)
    {
        const nlohmann::json& ntpServer = ntpServerObjects[index];
        if (ntpServer.is_null())
        {
            // Can't delete an item that doesn't exist
            if (currentNtpServer == currentNtpServers.end())
            {
                messages::propertyValueNotInList(asyncResp->res, "null",
                                                 "NTP/NTPServers/" +
                                                     std::to_string(index));

                return;
            }
            currentNtpServer = currentNtpServers.erase(currentNtpServer);
            continue;
        }
        const nlohmann::json::object_t* ntpServerObject =
            ntpServer.get_ptr<const nlohmann::json::object_t*>();
        if (ntpServerObject != nullptr)
        {
            if (!ntpServerObject->empty())
            {
                messages::propertyValueNotInList(
                    asyncResp->res,
                    ntpServer.dump(2, ' ', true,
                                   nlohmann::json::error_handler_t::replace),
                    "NTP/NTPServers/" + std::to_string(index));
                return;
            }
            // Can't retain an item that doesn't exist
            if (currentNtpServer == currentNtpServers.end())
            {
                messages::propertyValueOutOfRange(
                    asyncResp->res,
                    ntpServer.dump(2, ' ', true,
                                   nlohmann::json::error_handler_t::replace),
                    "NTP/NTPServers/" + std::to_string(index));

                return;
            }
            // empty objects should leave the NtpServer unmodified
            currentNtpServer++;
            continue;
        }

        const std::string* ntpServerStr =
            ntpServer.get_ptr<const std::string*>();
        if (ntpServerStr == nullptr)
        {
            messages::propertyValueTypeError(
                asyncResp->res,
                ntpServer.dump(2, ' ', true,
                               nlohmann::json::error_handler_t::replace),
                "NTP/NTPServers/" + std::to_string(index));
            return;
        }
        if (currentNtpServer == currentNtpServers.end())
        {
            // if we're at the end of the list, append to the end
            currentNtpServers.push_back(*ntpServerStr);
            currentNtpServer = currentNtpServers.end();
            continue;
        }
        *currentNtpServer = *ntpServerStr;
        currentNtpServer++;
    }

    // Any remaining array elements should be removed
    currentNtpServers.erase(currentNtpServer, currentNtpServers.end());

    constexpr std::array<std::string_view, 1> ethInterfaces = {
        "xyz.openbmc_project.Network.EthernetInterface"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project", 0, ethInterfaces, requestContext,
        [asyncResp, currentNtpServers](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message();
            messages::internalError(asyncResp->res);
            return;
        }

        for (const auto& [objectPath, serviceMap] : subtree)
        {
            for (const auto& [service, interfaces] : serviceMap)
            {
                for (const auto& interface : interfaces)
                {
                    if (interface !=
                        "xyz.openbmc_project.Network.EthernetInterface")
                    {
                        continue;
                    }

                    managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
                        asyncResp->strand_,
                        [asyncResp](const boost::system::error_code& ec2) {
                        if (ec2)
                        {
                            messages::internalError(asyncResp->res);
                            return;
                        }
                        },
                        service, objectPath, "org.freedesktop.DBus.Properties",
                        "Set", interface, "StaticNTPServers",
                        dbus::utility::DbusVariantType{currentNtpServers});
                }
            }
        }
    });
}

inline void
    handleProtocolEnabled(const bool protocolEnabled,
                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                          const std::string& netBasePath)
{
    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Control.Service.Attributes"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/control/service", 0, interfaces, requestContext,
        [protocolEnabled, asyncResp,
         netBasePath](const boost::system::error_code& ec,
                      const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            messages::internalError(asyncResp->res);
            return;
        }

        for (const auto& entry : subtree)
        {
            if (boost::algorithm::starts_with(entry.first, netBasePath))
            {
                managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
                    asyncResp->strand_,
                    [asyncResp](const boost::system::error_code& ec2) {
                    if (ec2)
                    {
                        messages::internalError(asyncResp->res);
                        return;
                    }
                    },
                    entry.second.begin()->first, entry.first,
                    "org.freedesktop.DBus.Properties", "Set",
                    "xyz.openbmc_project.Control.Service.Attributes", "Running",
                    dbus::utility::DbusVariantType{protocolEnabled});

                managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
                    asyncResp->strand_,
                    [asyncResp](const boost::system::error_code& ec2) {
                    if (ec2)
                    {
                        messages::internalError(asyncResp->res);
                        return;
                    }
                    },
                    entry.second.begin()->first, entry.first,
                    "org.freedesktop.DBus.Properties", "Set",
                    "xyz.openbmc_project.Control.Service.Attributes", "Enabled",
                    dbus::utility::DbusVariantType{protocolEnabled});
            }
        }
    });
}

inline std::string getHostName()
{
    std::string hostName;

    std::array<char, HOST_NAME_MAX> hostNameCStr{};
    if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0)
    {
        hostName = hostNameCStr.data();
    }
    return hostName;
}

inline void
    getNTPProtocolEnabled(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    dbus_utils::getProperty<std::string>(
        "xyz.openbmc_project.Settings", "/xyz/openbmc_project/time/sync_method",
        "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod",
        requestContext,
        [asyncResp](const boost::system::error_code& errorCode,
                    const std::string& timeSyncMethod) {
        if (errorCode)
        {
            return;
        }

        if (timeSyncMethod ==
            "xyz.openbmc_project.Time.Synchronization.Method.NTP")
        {
            asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = true;
        }
        else if (timeSyncMethod == "xyz.openbmc_project.Time.Synchronization."
                                   "Method.Manual")
        {
            asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = false;
        }
        });
}

inline std::string encodeServiceObjectPath(std::string_view serviceName)
{
    sdbusplus::message::object_path objPath(
        "/xyz/openbmc_project/control/service");
    objPath /= serviceName;
    return objPath.str;
}

inline void handleBmcNetworkProtocolHead(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    asyncResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby");
}

inline void handleManagersNetworkProtocolPatch(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{

    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    std::optional<std::string> newHostName;
    std::optional<std::vector<nlohmann::json>> ntpServerObjects;
    std::optional<bool> ntpEnabled;
    std::optional<bool> ipmiEnabled;
    std::optional<bool> sshEnabled;

    // clang-format off
        if (!json_util::readJsonPatch(
                req, asyncResp->res,
                "HostName", newHostName,
                "NTP/NTPServers", ntpServerObjects,
                "NTP/ProtocolEnabled", ntpEnabled,
                "IPMI/ProtocolEnabled", ipmiEnabled,
                "SSH/ProtocolEnabled", sshEnabled))
        {
            return;
        }
    // clang-format on

    asyncResp->res.result(boost::beast::http::status::no_content);
    if (newHostName)
    {
        messages::propertyNotWritable(asyncResp->res, "HostName");
        return;
    }

    if (ntpEnabled)
    {
        handleNTPProtocolEnabled(*ntpEnabled, asyncResp);
    }
    if (ntpServerObjects)
    {
        managedStore::ManagedObjectStoreContext context(asyncResp);
        getEthernetIfaceData(
            context,
            [asyncResp, ntpServerObjects](
                const bool success, std::vector<std::string>& currentNtpServers,
                const std::vector<std::string>& /*domainNames*/) {
            if (!success)
            {
                messages::internalError(asyncResp->res);
                return;
            }
            handleNTPServersPatch(asyncResp, *ntpServerObjects,
                                  std::move(currentNtpServers));
            });
    }

    if (ipmiEnabled)
    {
        handleProtocolEnabled(
            *ipmiEnabled, asyncResp,
            encodeServiceObjectPath(std::string(ipmiServiceName) + '@'));
    }

    if (sshEnabled)
    {
        handleProtocolEnabled(*sshEnabled, asyncResp,
                              encodeServiceObjectPath(sshServiceName));
    }
}

inline void handleManagersNetworkProtocolHead(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    asyncResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/ManagerNetworkProtocol/ManagerNetworkProtocol.json>; rel=describedby");
}

inline void handleManagersNetworkProtocolGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    handleManagersNetworkProtocolHead(app, req, asyncResp);
    getNetworkData(asyncResp, req);
}

inline void requestRoutesNetworkProtocol(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/")
        .privileges(redfish::privileges::patchManagerNetworkProtocol)
        .methods(boost::beast::http::verb::patch)(
            std::bind_front(handleManagersNetworkProtocolPatch, std::ref(app)));

    BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/")
        .privileges(redfish::privileges::headManagerNetworkProtocol)
        .methods(boost::beast::http::verb::head)(
            std::bind_front(handleManagersNetworkProtocolHead, std::ref(app)));

    BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/")
        .privileges(redfish::privileges::getManagerNetworkProtocol)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleManagersNetworkProtocolGet, std::ref(app)));
}

} // namespace redfish
