/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *
 *    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.
 */

/**
 * @file
 *
 * Defines a compound transport type (tuple) that can merge several transports
 * to look like a single one.
 */
#pragma once

#include <tuple>
#include <type_traits>

#include <transport/raw/Base.h>

namespace chip {
namespace Transport {

/**
 * Groups together several transports of different types and presents them as a unified transport.
 *
 * The usage intent is to be able to group several distinct transport types and make them look
 * as a single transport.
 *
 * Having an example class definition of `Tuple<UDP, UDP, TCP>`
 *
 * Is equivalent to:
 *
 * ~~~~~~~~~
 *    class TupleOfUdpUdpTcp : public BASE {
 *       private:
 *          UDP mUdp1;
 *          UDP mUdp2;
 *          TCP mTcp3;
 *       public:
 *          Init(UDPListenParameters &, UDPListenParameters&, TCPListenParameters) {...}
 *          CHIP_ERROR SendMessage(...) override;
 *          bool CanSendToPeer(...) override;
 *    }
 * ~~~~~~~~~
 *
 * The intent of this is to allow applications to use any transport types without CHIP pre-defining
 * popular mappings (like UDP only, UDP and BLE, BLE only etc.) and without using \#ifdefs to create
 * a single 'standard transport'.
 *
 * Transport logic:
 *   - Every transport can decide if a 'PeerAddress' can be sent over 'self'
 *
 *   - Within a mixed tuple, if several transports support a peer address (e.g. TCP and UDP both
 *     support IP), the first one found wins.
 *
 *   - Expected message sending logic:
 *     - BLE transports only support BLE. TCP/UDP support IP addresses
 *     - Multicasts only supported by UDP
 *
 * @tparam TransportTypes the ORDERED list of transport types grouped together. Order matters in
 *         determining what transport is used when multiple transports can reach a Peer.
 *
 * Transports (TransportTypes) are assumed to have an Init call with EXACTLY one argument and returning
 * a CHIP_ERROR, with a signature like:
 *
 *    CHIP_ERROR Init(AnyType);
 *
 */
template <typename... TransportTypes>
class Tuple : public Base
{
public:
    CHIP_ERROR SendMessage(const PeerAddress & address, System::PacketBufferHandle && msgBuf) override
    {
        return SendMessageImpl<0>(address, std::move(msgBuf));
    }

    CHIP_ERROR MulticastGroupJoinLeave(const Transport::PeerAddress & address, bool join) override
    {
        return MulticastGroupJoinLeaveImpl<0>(address, join);
    }

    bool CanSendToPeer(const PeerAddress & address) override { return CanSendToPeerImpl<0>(address); }

#if INET_CONFIG_ENABLE_TCP_ENDPOINT
    CHIP_ERROR TCPConnect(const PeerAddress & address, Transport::AppTCPConnectionCallbackCtxt * appState,
                          Transport::ActiveTCPConnectionState ** peerConnState) override
    {
        return TCPConnectImpl<0>(address, appState, peerConnState);
    }

    void TCPDisconnect(const PeerAddress & address) override { return TCPDisconnectImpl<0>(address); }

    void TCPDisconnect(Transport::ActiveTCPConnectionState * conn, bool shouldAbort = 0) override
    {
        return TCPDisconnectImpl<0>(conn, shouldAbort);
    }
#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT

    void Close() override { return CloseImpl<0>(); }

    /**
     * Initialization method that forwards arguments for initialization to each of the underlying
     * transports.
     *
     * Transports are assumed to have an Init call with EXACTLY one argument. This method MUST initialize
     * all underlying transports.
     *
     * @param delegate the delegate to handle messages.
     * @param args     initialization arguments, forwarded as-is to the underlying transports.
     */
    template <typename... Args, typename std::enable_if<(sizeof...(Args) == sizeof...(TransportTypes))>::type * = nullptr>
    CHIP_ERROR Init(RawTransportDelegate * delegate, Args &&... args)
    {
        return InitImpl(delegate, std::forward<Args>(args)...);
    }

private:
    /**
     * Recursive cansend implementation iterating through transport members.
     *
     * Will return true if any transport with index N and up can CanSendToPeer(address);
     *
     * @tparam N the index of the underlying transport to check for CanSendToPeer
     *
     * @param address what address to check.
     */
    template <size_t N, typename std::enable_if<(N < sizeof...(TransportTypes))>::type * = nullptr>
    bool CanSendToPeerImpl(const PeerAddress & address)
    {
        return std::get<N>(mTransports).CanSendToPeer(address) || CanSendToPeerImpl<N + 1>(address);
    }

    /**
     * CanSend template for out of range N. Always returns false.
     */
    template <size_t N, typename std::enable_if<(N >= sizeof...(TransportTypes))>::type * = nullptr>
    bool CanSendToPeerImpl(const PeerAddress & address)
    {
        return false;
    }

#if INET_CONFIG_ENABLE_TCP_ENDPOINT
    /**
     * Recursive TCPConnect implementation iterating through transport members.
     *
     * @tparam N the index of the underlying transport to send disconnect to
     *
     * @param address what address to connect to.
     */
    template <size_t N, typename std::enable_if<(N < sizeof...(TransportTypes))>::type * = nullptr>
    CHIP_ERROR TCPConnectImpl(const PeerAddress & address, Transport::AppTCPConnectionCallbackCtxt * appState,
                              Transport::ActiveTCPConnectionState ** peerConnState)
    {
        Base * base = &std::get<N>(mTransports);
        if (base->CanSendToPeer(address))
        {
            return base->TCPConnect(address, appState, peerConnState);
        }
        return TCPConnectImpl<N + 1>(address, appState, peerConnState);
    }

    /**
     * TCPConnectImpl template for out of range N.
     */
    template <size_t N, typename std::enable_if<(N >= sizeof...(TransportTypes))>::type * = nullptr>
    CHIP_ERROR TCPConnectImpl(const PeerAddress & address, Transport::AppTCPConnectionCallbackCtxt * appState,
                              Transport::ActiveTCPConnectionState ** peerConnState)
    {
        return CHIP_ERROR_NO_MESSAGE_HANDLER;
    }

    /**
     * Recursive disconnect implementation iterating through transport members.
     *
     * @tparam N the index of the underlying transport to send disconnect to
     *
     * @param address what address to disconnect from.
     */
    template <size_t N, typename std::enable_if<(N < sizeof...(TransportTypes))>::type * = nullptr>
    void TCPDisconnectImpl(const PeerAddress & address)
    {
        std::get<N>(mTransports).TCPDisconnect(address);
        TCPDisconnectImpl<N + 1>(address);
    }

    /**
     * TCPDisconnectImpl template for out of range N.
     */
    template <size_t N, typename std::enable_if<(N >= sizeof...(TransportTypes))>::type * = nullptr>
    void TCPDisconnectImpl(const PeerAddress & address)
    {}

    /**
     * Recursive disconnect implementation iterating through transport members.
     *
     * @tparam N the index of the underlying transport to send disconnect to
     *
     * @param conn pointer to the connection to the peer.
     */
    template <size_t N, typename std::enable_if<(N < sizeof...(TransportTypes))>::type * = nullptr>
    void TCPDisconnectImpl(Transport::ActiveTCPConnectionState * conn, bool shouldAbort = 0)
    {
        std::get<N>(mTransports).TCPDisconnect(conn, shouldAbort);
        TCPDisconnectImpl<N + 1>(conn, shouldAbort);
    }

    /**
     * TCPDisconnectImpl template for out of range N.
     */
    template <size_t N, typename std::enable_if<(N >= sizeof...(TransportTypes))>::type * = nullptr>
    void TCPDisconnectImpl(Transport::ActiveTCPConnectionState * conn, bool shouldAbort = 0)
    {}
#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT

    /**
     * Recursive disconnect implementation iterating through transport members.
     *
     * @tparam N the index of the underlying transport to send close to
     */
    template <size_t N, typename std::enable_if<(N < sizeof...(TransportTypes))>::type * = nullptr>
    void CloseImpl()
    {
        std::get<N>(mTransports).Close();
        CloseImpl<N + 1>();
    }

    /**
     * CloseImpl template for out of range N.
     */
    template <size_t N, typename std::enable_if<(N >= sizeof...(TransportTypes))>::type * = nullptr>
    void CloseImpl()
    {}

    /**
     * Recursive sendmessage implementation iterating through transport members.
     *
     * Message is sent through the first transport from index N or above, which returns 'CanSendToPeer'
     *
     * @tparam N the index of the underlying transport to run SendMessage throug.
     *
     * @param address where to send the message
     * @param msgBuf the message to send.  Includes all CHIP message fields except optional length.
     */
    template <size_t N, typename std::enable_if<(N < sizeof...(TransportTypes))>::type * = nullptr>
    CHIP_ERROR SendMessageImpl(const PeerAddress & address, System::PacketBufferHandle && msgBuf)
    {
        Base * base = &std::get<N>(mTransports);
        if (base->CanSendToPeer(address))
        {
            return base->SendMessage(address, std::move(msgBuf));
        }
        return SendMessageImpl<N + 1>(address, std::move(msgBuf));
    }

    /**
     * SendMessageImpl when N is out of range. Always returns an error code.
     */
    template <size_t N, typename std::enable_if<(N >= sizeof...(TransportTypes))>::type * = nullptr>
    CHIP_ERROR SendMessageImpl(const PeerAddress & address, System::PacketBufferHandle msgBuf)
    {
        return CHIP_ERROR_NO_MESSAGE_HANDLER;
    }

    /**
     * Recursive GroupJoinLeave implementation iterating through transport members.
     *
     * Listener is activated through the first transport from index N or above, which returns 'CanListenMulticast'
     *
     * @tparam N the index of the underlying transport to run GroupJoinLeave through.
     *
     * @param address where to send the message
     * @param join a boolean indicating if the transport should join or leave the group
     */
    template <size_t N, typename std::enable_if<(N < sizeof...(TransportTypes))>::type * = nullptr>
    CHIP_ERROR MulticastGroupJoinLeaveImpl(const Transport::PeerAddress & address, bool join)
    {
        Base * base = &std::get<N>(mTransports);
        if (base->CanListenMulticast())
        {
            return base->MulticastGroupJoinLeave(address, join);
        }
        return MulticastGroupJoinLeaveImpl<N + 1>(address, join);
    }

    /**
     * GroupJoinLeave when N is out of range. Always returns an error code.
     */
    template <size_t N, typename std::enable_if<(N >= sizeof...(TransportTypes))>::type * = nullptr>
    CHIP_ERROR MulticastGroupJoinLeaveImpl(const Transport::PeerAddress & address, bool join)
    {
        return CHIP_ERROR_NO_MESSAGE_HANDLER;
    }

    /**
     * Recursive init implementation iterating through transport members
     *
     * Given a set of arguments 'a1, a2, a3, ... aN' will call an Init method on the last N
     * transports.
     *
     * Method is expected to be called initially with exactly sizeof(TransportTypes) to initialize
     * all transports.
     *
     * @param arg the next initialize argument to pass to the transport Init method
     * @param rest tail arguments to be passed to the rest of transport Init methods.
     */
    template <typename InitArg, typename... Rest>
    CHIP_ERROR InitImpl(RawTransportDelegate * delegate, InitArg && arg, Rest &&... rest)
    {
        auto transport = &std::get<sizeof...(TransportTypes) - sizeof...(Rest) - 1>(mTransports);

        CHIP_ERROR err = transport->Init(std::forward<InitArg>(arg));
        if (err != CHIP_NO_ERROR)
        {
            return err;
        }

        transport->SetDelegate(delegate);

        return InitImpl(delegate, std::forward<Rest>(rest)...);
    }

    /**
     * Base case where initialization finishes.
     *
     * Provided to ensure that recursive InitImpl finishes compiling.
     */
    CHIP_ERROR InitImpl(RawTransportDelegate * delegate) { return CHIP_NO_ERROR; }

    std::tuple<TransportTypes...> mTransports;

public:
    template <size_t i>
    auto GetImplAtIndex() -> decltype(std::get<i>(mTransports)) &
    {
        return std::get<i>(mTransports);
    }

    std::tuple<TransportTypes...> & GetTransports() { return mTransports; }
};

} // namespace Transport
} // namespace chip
