#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::optional<std::tuple<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 std::nullopt;
        }
        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
