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

#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "managed_store_types.hpp"

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

#include <array>
#include <charconv>
#include <string_view>

namespace redfish
{

enum NetworkProtocolUnitStructFields
{
    NET_PROTO_UNIT_NAME,
    NET_PROTO_UNIT_DESC,
    NET_PROTO_UNIT_LOAD_STATE,
    NET_PROTO_UNIT_ACTIVE_STATE,
    NET_PROTO_UNIT_SUB_STATE,
    NET_PROTO_UNIT_DEVICE,
    NET_PROTO_UNIT_OBJ_PATH,
    NET_PROTO_UNIT_ALWAYS_0,
    NET_PROTO_UNIT_ALWAYS_EMPTY,
    NET_PROTO_UNIT_ALWAYS_ROOT_PATH
};

enum NetworkProtocolListenResponseElements
{
    NET_PROTO_LISTEN_TYPE,
    NET_PROTO_LISTEN_STREAM
};

/**
 * @brief D-Bus Unit structure returned in array from ListUnits Method
 */
using UnitStruct =
    std::tuple<std::string, std::string, std::string, std::string, std::string,
               std::string, sdbusplus::message::object_path, uint32_t,
               std::string, sdbusplus::message::object_path>;

template <typename CallbackFunc>
void getMainChassisId(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
                      CallbackFunc&& callback)
{
    // Find managed chassis
    constexpr std::array<std::string_view, 2> interfaces = {
        "xyz.openbmc_project.Inventory.Item.Board",
        "xyz.openbmc_project.Inventory.Item.Chassis"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::managedObjectStore->getSubTree(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [callback,
         asyncResp](const boost::system::error_code& ec,
                    const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << ec;
            return;
        }
        if (subtree.empty())
        {
            BMCWEB_LOG_DEBUG << "Can't find chassis!";
            return;
        }

        std::size_t idPos = subtree[0].first.rfind('/');
        if (idPos == std::string::npos ||
            (idPos + 1) >= subtree[0].first.size())
        {
            messages::internalError(asyncResp->res);
            BMCWEB_LOG_DEBUG << "Can't parse chassis ID!";
            return;
        }
        std::string chassisId = subtree[0].first.substr(idPos + 1);
        BMCWEB_LOG_DEBUG << "chassisId = " << chassisId;
        callback(chassisId, asyncResp);
    });
}

template <typename CallbackFunc>
void getPortStatusAndPath(
    std::span<const std::pair<std::string_view, std::string_view>>
        protocolToDBus,
    CallbackFunc&& callback)
{
    crow::connections::systemBus->async_method_call(
        [protocolToDBus, callback{std::forward<CallbackFunc>(callback)}](
            const boost::system::error_code& ec,
            const std::vector<UnitStruct>& r) {
        std::vector<std::tuple<std::string, std::string, bool>> socketData;
        if (ec)
        {
            BMCWEB_LOG_ERROR << ec;
            // return error code
            callback(ec, socketData);
            return;
        }

        // save all service output into vector
        for (const UnitStruct& unit : r)
        {
            // Only traverse through <xyz>.socket units
            const std::string& unitName = std::get<NET_PROTO_UNIT_NAME>(unit);

            // find "." into unitsName
            size_t lastCharPos = unitName.rfind('.');
            if (lastCharPos == std::string::npos)
            {
                continue;
            }

            // is unitsName end with ".socket"
            std::string unitNameEnd = unitName.substr(lastCharPos);
            if (unitNameEnd != ".socket")
            {
                continue;
            }

            // find "@" into unitsName
            if (size_t atCharPos = unitName.rfind('@');
                atCharPos != std::string::npos)
            {
                lastCharPos = atCharPos;
            }

            // unitsName without "@eth(x).socket", only <xyz>
            // unitsName without ".socket", only <xyz>
            std::string unitNameStr = unitName.substr(0, lastCharPos);

            for (const auto& kv : protocolToDBus)
            {
                // We are interested in services, which starts with
                // mapped service name
                if (unitNameStr != kv.second)
                {
                    continue;
                }

                const std::string& socketPath =
                    std::get<NET_PROTO_UNIT_OBJ_PATH>(unit);
                const std::string& unitState =
                    std::get<NET_PROTO_UNIT_SUB_STATE>(unit);

                bool isProtocolEnabled =
                    ((unitState == "running") || (unitState == "listening"));

                socketData.emplace_back(socketPath, std::string(kv.first),
                                        isProtocolEnabled);
                // We found service, return from inner loop.
                break;
            }
        }

        callback(ec, socketData);
        },
        "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
        "org.freedesktop.systemd1.Manager", "ListUnits");
}

template <typename CallbackFunc>
void getPortNumber(
    const std::string& socketPath,
    const managedStore::ManagedObjectStoreContext& requestContext,
    CallbackFunc&& callback)
{
    dbus_utils::getProperty<std::vector<std::tuple<std::string, std::string>>>(
        "org.freedesktop.systemd1", socketPath,
        "org.freedesktop.systemd1.Socket", "Listen", requestContext,
        [callback{std::forward<CallbackFunc>(callback)}](
            const boost::system::error_code& ec,
            const std::vector<std::tuple<std::string, std::string>>& resp) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << ec;
            callback(ec, 0);
            return;
        }
        if (resp.empty())
        {
            // Network Protocol Listen Response Elements is empty
            boost::system::error_code ec1 =
                boost::system::errc::make_error_code(
                    boost::system::errc::bad_message);
            // return error code
            callback(ec1, 0);
            BMCWEB_LOG_ERROR << ec1;
            return;
        }
        const std::string& listenStream =
            std::get<NET_PROTO_LISTEN_STREAM>(resp[0]);
        const char* pa = &listenStream[listenStream.rfind(':') + 1];
        int port{0};
        if (auto [p, ec2] = std::from_chars(pa, nullptr, port);
            ec2 != std::errc())
        {
            // there is only two possibility invalid_argument and
            // result_out_of_range
            boost::system::error_code ec3 =
                boost::system::errc::make_error_code(
                    boost::system::errc::invalid_argument);
            if (ec2 == std::errc::result_out_of_range)
            {
                ec3 = boost::system::errc::make_error_code(
                    boost::system::errc::result_out_of_range);
            }
            // return error code
            callback(ec3, 0);
            BMCWEB_LOG_ERROR << ec3;
        }
        callback(ec, port);
        });
}

} // namespace redfish
#endif
