/*
// 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

#ifndef BOOST_COROUTINES_NO_DEPRECATION_WARNING
// users should define this if they directly include boost/asio/spawn.hpp,
// but by defining it here, warnings won't cause problems with a compile
#define BOOST_COROUTINES_NO_DEPRECATION_WARNING
#endif

#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/callable_traits.hpp>
#include <chrono>
#include <sdbusplus/asio/detail/async_send_handler.hpp>
#include <sdbusplus/message.hpp>
#include <sdbusplus/utility/read_into_tuple.hpp>
#include <sdbusplus/utility/type_traits.hpp>
#include <string>
#include <tuple>

namespace sdbusplus
{

namespace asio
{

/// Root D-Bus IO object
/**
 * A connection to a bus, through which messages may be sent or received.
 */
class connection : public sdbusplus::bus::bus
{
  public:
    // default to system bus
    connection(boost::asio::io_context& io) :
        sdbusplus::bus::bus(sdbusplus::bus::new_default()), io_(io), socket(io_)
    {
        socket.assign(get_fd());
        read_wait();
    }
    connection(boost::asio::io_context& io, sd_bus* bus) :
        sdbusplus::bus::bus(bus), io_(io), socket(io_)
    {
        socket.assign(get_fd());
        read_wait();
    }
    ~connection()
    {
        // The FD will be closed by the socket object, so assign null to the
        // sd_bus object to avoid a double close()  Ignore return codes here,
        // because there's nothing we can do about errors
        socket.release();
    }

    /** @brief Perform an asynchronous send of a message, executing the handler
     *         upon return and return
     *
     *  @param[in] m - A message ready to send
     *  @param[in] handler - handler to execute upon completion; this may be an
     *                       asio::yield_context to execute asynchronously as a
     *                       coroutine
     *
     *  @return If a yield context is passed as the handler, the return type is
     *          a message. If a function object is passed in as the handler,
     *          the return type is the result of the handler registration,
     *          while the resulting message will get passed into the handler.
     */
    template <typename MessageHandler>
    inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler,
                                         void(boost::system::error_code,
                                              message::message&))
        async_send(message::message& m, MessageHandler&& handler)
    {
        boost::asio::async_completion<
            MessageHandler, void(boost::system::error_code, message::message)>
            init(handler);
        detail::async_send_handler<typename boost::asio::async_result<
            MessageHandler, void(boost::system::error_code,
                                 message::message)>::completion_handler_type>(
            std::move(init.completion_handler))(get(), m);
        return init.result.get();
    }

    /** @brief Perform an asynchronous method call, with input parameter packing
     *         and return value unpacking
     *
     *  @param[in] handler - A function object that is to be called as a
     *                       continuation for the async dbus method call. The
     *                       arguments to parse on the return are deduced from
     *                       the handler's signature and then passed in along
     *                       with an error code and optional message::message
     *  @param[in] service - The service to call.
     *  @param[in] objpath - The object's path for the call.
     *  @param[in] interf - The object's interface to call.
     *  @param[in] method - The object's method to call.
     *  @param[in] a... - Optional parameters for the method call.
     *
     *  @return immediate return of the internal handler registration. The
     *          result of the actual asynchronous call will get unpacked from
     *          the message and passed into the handler when the call is
     *          complete.
     */
    template <typename MessageHandler, typename... InputArgs>
    void async_method_call(MessageHandler&& handler, const std::string& service,
                           const std::string& objpath,
                           const std::string& interf, const std::string& method,
                           const InputArgs&... a)
    {
        using FunctionTuple = boost::callable_traits::args_t<MessageHandler>;
        using FunctionTupleType =
            typename utility::decay_tuple<FunctionTuple>::type;
        constexpr bool returnWithMsg = []() {
            if constexpr (std::tuple_size_v<FunctionTupleType>> 1)
            {
                return std::is_same_v<
                    std::tuple_element_t<1, FunctionTupleType>,
                    sdbusplus::message::message>;
            }
            return false;
        }();
        using UnpackType =
            typename utility::strip_first_n_args<returnWithMsg ? 2 : 1,
                                                 FunctionTupleType>::type;
        auto applyHandler = [handler = std::forward<MessageHandler>(handler)](
                                boost::system::error_code ec,
                                message::message& r) mutable {
            UnpackType responseData;
            if (!ec)
            {
                try
                {
                    utility::read_into_tuple(responseData, r);
                }
                catch (const std::exception& e)
                {
                    // Set error code if not already set
                    ec = boost::system::errc::make_error_code(
                        boost::system::errc::invalid_argument);
                }
            }
            // Note.  Callback is called whether or not the unpack was
            // successful to allow the user to implement their own handling
            if constexpr (returnWithMsg)
            {
                auto response = std::tuple_cat(std::make_tuple(ec),
                                               std::forward_as_tuple(r),
                                               std::move(responseData));
                std::apply(handler, response);
            }
            else
            {
                auto response = std::tuple_cat(std::make_tuple(ec),
                                               std::move(responseData));
                std::apply(handler, response);
            }
        };
        message::message m;
        boost::system::error_code ec;
        try
        {
            m = new_method_call(service.c_str(), objpath.c_str(),
                                interf.c_str(), method.c_str());
            m.append(a...);
        }
        catch (const exception::SdBusError& e)
        {
            ec = boost::system::errc::make_error_code(
                static_cast<boost::system::errc::errc_t>(e.get_errno()));
            applyHandler(ec, m);
            return;
        }
        async_send(m, std::forward<decltype(applyHandler)>(applyHandler));
    }

    /** @brief Perform a yielding asynchronous method call, with input
     *         parameter packing and return value unpacking
     *
     *  @param[in] yield - A yield context to async block upon.
     *  @param[in] ec - an error code that will be set for any errors
     *  @param[in] service - The service to call.
     *  @param[in] objpath - The object's path for the call.
     *  @param[in] interf - The object's interface to call.
     *  @param[in] method - The object's method to call.
     *  @param[in] a... - Optional parameters for the method call.
     *
     *  @return Unpacked value of RetType
     */
    template <typename... RetTypes, typename... InputArgs>
    auto yield_method_call(boost::asio::yield_context yield,
                           boost::system::error_code& ec,
                           const std::string& service,
                           const std::string& objpath,
                           const std::string& interf, const std::string& method,
                           const InputArgs&... a)
    {
        message::message m;
        try
        {
            m = new_method_call(service.c_str(), objpath.c_str(),
                                interf.c_str(), method.c_str());
            m.append(a...);
        }
        catch (const exception::SdBusError& e)
        {
            ec = boost::system::errc::make_error_code(
                static_cast<boost::system::errc::errc_t>(e.get_errno()));
        }
        message::message r;
        if (!ec)
        {
            r = async_send(m, yield[ec]);
        }
        if constexpr (sizeof...(RetTypes) == 0)
        {
            // void return
            return;
        }
        else if constexpr (sizeof...(RetTypes) == 1)
        {
            if constexpr (std::is_same<utility::first_type<RetTypes...>,
                                       void>::value)
            {
                return;
            }
            else
            {
                // single item return
                utility::first_type<RetTypes...> responseData;
                // before attempting to read, check ec and bail on error
                if (ec)
                {
                    return responseData;
                }
                try
                {
                    r.read(responseData);
                }
                catch (const std::exception& e)
                {
                    ec = boost::system::errc::make_error_code(
                        boost::system::errc::invalid_argument);
                    // responseData will be default-constructed...
                }
                return responseData;
            }
        }
        else
        {
            // tuple of things to return
            std::tuple<RetTypes...> responseData;
            // before attempting to read, check ec and bail on error
            if (ec)
            {
                return responseData;
            }
            try
            {
                r.read(responseData);
            }
            catch (const std::exception& e)
            {
                ec = boost::system::errc::make_error_code(
                    boost::system::errc::invalid_argument);
                // responseData will be default-constructed...
            }
            return responseData;
        }
    }

    boost::asio::io_context& get_io_context()
    {
        return io_;
    }

  private:
    boost::asio::io_context& io_;
    boost::asio::posix::stream_descriptor socket;

    void read_wait()
    {
        socket.async_read_some(
            boost::asio::null_buffers(),
            [&](const boost::system::error_code& ec, std::size_t) {
                if (process_discard())
                {
                    read_immediate();
                }
                else
                {
                    read_wait();
                }
            });
    }
    void read_immediate()
    {
        boost::asio::post(io_, [&] {
            if (process_discard())
            {
                read_immediate();
            }
            else
            {
                read_wait();
            }
        });
    }
};

} // namespace asio

} // namespace sdbusplus
