// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright OpenBMC Authors
#pragma once
#include "dbus_utility.hpp"
#include "logging.hpp"

#include <sys/socket.h>

#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/address.hpp>
#include <boost/asio/ip/address_v4.hpp>
#include <boost/asio/ip/address_v6.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/system/errc.hpp>

#include <charconv>
#include <cstdint>
#include <string>
#include <string_view>
#include <system_error>
#include <tuple>
#include <vector>

namespace async_resolve
{

inline bool endpointFromResolveTuple(const std::vector<uint8_t>& ipAddress,
                                     boost::asio::ip::tcp::endpoint& endpoint)
{
    if (ipAddress.size() == 4) // ipv4 address
    {
        BMCWEB_LOG_DEBUG("ipv4 address");
        boost::asio::ip::address_v4 ipv4Addr(
            {ipAddress[0], ipAddress[1], ipAddress[2], ipAddress[3]});
        endpoint.address(ipv4Addr);
    }
    else if (ipAddress.size() == 16) // ipv6 address
    {
        BMCWEB_LOG_DEBUG("ipv6 address");
        boost::asio::ip::address_v6 ipv6Addr(
            {ipAddress[0], ipAddress[1], ipAddress[2], ipAddress[3],
             ipAddress[4], ipAddress[5], ipAddress[6], ipAddress[7],
             ipAddress[8], ipAddress[9], ipAddress[10], ipAddress[11],
             ipAddress[12], ipAddress[13], ipAddress[14], ipAddress[15]});
        endpoint.address(ipv6Addr);
    }
    else
    {
        BMCWEB_LOG_ERROR("Resolve failed to fetch the IP address");
        return false;
    }
    return true;
}

class Resolver
{
  public:
    // unused io param used to keep interface identical to
    // boost::asio::tcp:::resolver
    explicit Resolver(boost::asio::io_context& /*io*/) {}

    ~Resolver() = default;

    Resolver(const Resolver&) = delete;
    Resolver(Resolver&&) = delete;
    Resolver& operator=(const Resolver&) = delete;
    Resolver& operator=(Resolver&&) = delete;

    using results_type = std::vector<boost::asio::ip::tcp::endpoint>;

    template <typename ResolveHandler>
    // This function is kept using snake case so that it is interoperable with
    // boost::asio::ip::tcp::resolver
    // NOLINTNEXTLINE(readability-identifier-naming)
    void async_resolve(std::string_view host, std::string_view port,
                       ResolveHandler&& handler)
    {
        BMCWEB_LOG_DEBUG("Trying to resolve: {}:{}", host, port);

        uint16_t portNum = 0;

        auto it = std::from_chars(&*port.begin(), &*port.end(), portNum);
        if (it.ec != std::errc())
        {
            BMCWEB_LOG_ERROR("Failed to get the Port");
            handler(std::make_error_code(std::errc::invalid_argument),
                    results_type{});

            return;
        }

        uint64_t flag = 0;
        dbus::utility::async_method_call(
            [host{std::string(host)}, portNum,
             handler = std::forward<ResolveHandler>(handler)](
                const boost::system::error_code& ec,
                const std::vector<
                    std::tuple<int32_t, int32_t, std::vector<uint8_t>>>& resp,
                const std::string& hostName, const uint64_t flagNum) {
                results_type endpointList;
                if (ec)
                {
                    BMCWEB_LOG_ERROR("Resolve failed: {}", ec.message());
                    handler(ec, endpointList);
                    return;
                }
                BMCWEB_LOG_DEBUG("ResolveHostname returned: {}:{}", hostName,
                                 flagNum);
                // Extract the IP address from the response
                for (const std::tuple<int32_t, int32_t, std::vector<uint8_t>>&
                         resolveList : resp)
                {
                    boost::asio::ip::tcp::endpoint endpoint;
                    endpoint.port(portNum);
                    if (!endpointFromResolveTuple(std::get<2>(resolveList),
                                                  endpoint))
                    {
                        boost::system::error_code ecErr = make_error_code(
                            boost::system::errc::address_not_available);
                        handler(ecErr, endpointList);
                    }
                    BMCWEB_LOG_DEBUG("resolved endpoint is : {}",
                                     endpoint.address().to_string());
                    endpointList.push_back(endpoint);
                }
                // All the resolved data is filled in the endpointList
                handler(ec, endpointList);
            },
            "org.freedesktop.resolve1", "/org/freedesktop/resolve1",
            "org.freedesktop.resolve1.Manager", "ResolveHostname", 0, host,
            AF_UNSPEC, flag);
    }
};

} // namespace async_resolve
