#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>

#include <stdplus/exception.hpp>
#include <stdplus/fd/impl.hpp>
#include <stdplus/util/cexec.hpp>

#include <format>
#include <string_view>

namespace stdplus
{
namespace fd
{

using namespace std::literals::string_view_literals;

std::span<std::byte> FdImpl::read(std::span<std::byte> buf)
{
    ssize_t amt = ::read(get(), buf.data(), buf.size());
    if (amt == -1)
    {
        if (errno == EAGAIN || errno == EWOULDBLOCK)
        {
            return {};
        }
        throw util::makeSystemError(errno, "read");
    }
    else if (amt == 0)
    {
        throw exception::Eof("read");
    }
    return buf.subspan(0, amt);
}

std::span<std::byte> FdImpl::recv(std::span<std::byte> buf, RecvFlags flags)
{
    ssize_t amt = ::recv(get(), buf.data(), buf.size(),
                         static_cast<int>(flags));
    if (amt == -1)
    {
        if (errno == EAGAIN || errno == EWOULDBLOCK)
        {
            return {};
        }
        throw util::makeSystemError(errno, "recv");
    }
    else if (amt == 0)
    {
        throw exception::Eof("recv");
    }
    return buf.subspan(0, amt);
}

std::span<const std::byte> FdImpl::write(std::span<const std::byte> data)
{
    ssize_t amt = ::write(get(), data.data(), data.size());
    if (amt == -1)
    {
        if (errno == EAGAIN || errno == EWOULDBLOCK)
        {
            return {};
        }
        throw util::makeSystemError(errno, "write");
    }
    return data.subspan(0, amt);
}

std::span<const std::byte> FdImpl::send(std::span<const std::byte> data,
                                        SendFlags flags)
{
    ssize_t amt = ::send(get(), data.data(), data.size(),
                         static_cast<int>(flags));
    if (amt == -1)
    {
        if (errno == EAGAIN || errno == EWOULDBLOCK)
        {
            return {};
        }
        throw util::makeSystemError(errno, "send");
    }
    return data.subspan(0, amt);
}

static std::string_view whenceStr(Whence whence)
{
    switch (whence)
    {
        case Whence::Set:
            return "set"sv;
        case Whence::Cur:
            return "cur"sv;
        case Whence::End:
            return "end"sv;
        default:
            return "Unknown whence"sv;
    }
}

size_t FdImpl::lseek(off_t offset, Whence whence)
{
    return CHECK_ERRNO(::lseek(get(), offset, static_cast<int>(whence)),
                       std::format("lseek {}B {}", offset, whenceStr(whence)));
}

void FdImpl::truncate(off_t size)
{
    CHECK_ERRNO(::ftruncate(get(), size), std::format("ftruncate {}B", size));
}

void FdImpl::bind(std::span<const std::byte> sockaddr)
{
    CHECK_ERRNO(
        ::bind(get(), reinterpret_cast<const struct sockaddr*>(sockaddr.data()),
               sockaddr.size()),
        "bind");
}

void FdImpl::listen(int backlog)
{
    CHECK_ERRNO(::listen(get(), backlog), "listen");
}

std::tuple<std::optional<int>, std::span<std::byte>>
    FdImpl::accept(std::span<std::byte> sockaddr)
{
    socklen_t len = sockaddr.size();
    auto fd = ::accept(
        get(), reinterpret_cast<struct sockaddr*>(sockaddr.data()), &len);
    if (fd == -1)
    {
        if (errno == EAGAIN || errno == EWOULDBLOCK)
        {
            return {};
        }
        throw util::makeSystemError(errno, "accept");
    }
    return std::make_tuple(fd, sockaddr.subspan(0, len));
}

void FdImpl::setsockopt(SockLevel level, SockOpt optname,
                        std::span<const std::byte> opt)
{
    CHECK_ERRNO(::setsockopt(get(), static_cast<int>(level),
                             static_cast<int>(optname), opt.data(), opt.size()),
                "setsockopt");
}

int FdImpl::ioctl(unsigned long id, void* data)
{
    return constIoctl(id, data);
}

int FdImpl::constIoctl(unsigned long id, void* data) const
{
    return CHECK_ERRNO(::ioctl(get(), id, data),
                       std::format("ioctl {:#x}", id));
}

void FdImpl::fcntlSetfd(FdFlags flags)
{
    CHECK_ERRNO(::fcntl(get(), F_SETFD, static_cast<int>(flags)),
                "fcntl setfd");
}

FdFlags FdImpl::fcntlGetfd() const
{
    return FdFlags(CHECK_ERRNO(::fcntl(get(), F_GETFD), "fcntl getfd"));
}

void FdImpl::fcntlSetfl(FileFlags flags)
{
    CHECK_ERRNO(::fcntl(get(), F_SETFL, static_cast<int>(flags)),
                "fcntl setfl");
}

FileFlags FdImpl::fcntlGetfl() const
{
    return FileFlags(CHECK_ERRNO(::fcntl(get(), F_GETFL), "fcntl getfl"));
}

std::span<std::byte> FdImpl::mmap(std::span<std::byte> window, ProtFlags prot,
                                  MMapFlags flags, off_t offset)
{
    auto ret = ::mmap(window.data(), window.size(), static_cast<int>(prot),
                      static_cast<int>(flags), get(), offset);
    if (ret == MAP_FAILED)
    {
        util::doError(errno, "mmap");
    }
    return {reinterpret_cast<std::byte*>(ret), window.size()};
}

void FdImpl::munmap(std::span<std::byte> window)
{
    CHECK_ERRNO(::munmap(window.data(), window.size()), "munmap");
}

} // namespace fd
} // namespace stdplus
