/*
 *  Copyright (C) 2004-2023 Savoir-faire Linux Inc.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <https://www.gnu.org/licenses/>.
 */
#pragma once

#include "ip_utils.h"

#include <functional>
#include <vector>
#include <chrono>
#include <system_error>
#include <cstdint>

#if defined(_MSC_VER)
#include <BaseTsd.h>
using ssize_t = SSIZE_T;
#endif

namespace dhtnet {

template<typename T>
class GenericSocket
{
public:
    using ValueType = T;

    virtual ~GenericSocket() { shutdown(); }

    using RecvCb = std::function<ssize_t(const ValueType* buf, std::size_t len)>;

    /// Close established connection
    /// \note Terminate outstanding blocking read operations with an empty error code, but a 0 read size.
    virtual void shutdown() {}

    /// Set Rx callback
    /// \warning This method is here for backward compatibility
    /// and because async IO are not implemented yet.
    virtual void setOnRecv(RecvCb&& cb) = 0;

    virtual bool isReliable() const = 0;

    virtual bool isInitiator() const = 0;

    /// Return maximum application payload size.
    /// This value is negative if the session is not ready to give a valid answer.
    /// The value is 0 if such information is irrelevant for the session.
    /// If stricly positive, the user must use send() with an input buffer size below or equals
    /// to this value if it want to be sure that the transport sent it in an atomic way.
    /// Example: in case of non-reliable transport using packet oriented IO,
    /// this value gives the maximal size used to send one packet.
    virtual int maxPayload() const = 0;

    /// Wait until data to read available, timeout or io error
    /// \param ec error code set in case of error (if return value is < 0)
    /// \return positive number if data ready for read, 0 in case of timeout or error.
    /// \note error code is not set in case of timeout, but set only in case of io error
    /// (i.e. socket deconnection).
    /// \todo make a std::chrono version for the timeout
    virtual int waitForData(std::chrono::milliseconds timeout, std::error_code& ec) const = 0;

    /// Write a given amount of data.
    /// \param buf data to write.
    /// \param len number of bytes to write.
    /// \param ec error code set in case of error.
    /// \return number of bytes written, 0 is valid.
    /// \warning error checking consists in checking if \a !ec is true, not if returned size is 0
    /// as a write of 0 could be considered a valid operation.
    virtual std::size_t write(const ValueType* buf, std::size_t len, std::error_code& ec) = 0;

    /// Read a given amount of data.
    /// \param buf data to read.
    /// \param len number of bytes to read.
    /// \param ec error code set in case of error.
    /// \return number of bytes read, 0 is valid.
    /// \warning error checking consists in checking if \a !ec is true, not if returned size is 0
    /// as a read of 0 could be considered a valid operation (i.e. non-blocking IO).
    virtual std::size_t read(ValueType* buf, std::size_t len, std::error_code& ec) = 0;

    /// write() adaptor for STL containers
    template<typename U>
    std::size_t write(const U& obj, std::error_code& ec)
    {
        return write(obj.data(), obj.size() * sizeof(typename U::value_type), ec);
    }

    /// read() adaptor for STL containers
    template<typename U>
    std::size_t read(U& storage, std::error_code& ec)
    {
        auto res = read(storage.data(), storage.size() * sizeof(typename U::value_type), ec);
        if (!ec)
            storage.resize(res);
        return res;
    }

    /// Return the local IP address if known.
    /// \note The address is not valid (addr.isUnspecified() returns true) if it's not known
    /// or not available.
    virtual IpAddr localAddr() const { return {}; }

    /// Return the remote IP address if known.
    /// \note The address is not valid (addr.isUnspecified() returns true) if it's not known
    /// or not available.
    virtual IpAddr remoteAddr() const { return {}; }

protected:
    GenericSocket() = default;
};

} // namespace jami
