#include "io.hpp"

#include "internal/sys.hpp"

#include <fcntl.h>

#include <cstdint>
#include <cstring>
#include <string>

namespace host_tool
{

const std::string DevMemDevice::devMemPath = "/dev/mem";

bool DevMemDevice::read(const std::size_t offset, const std::size_t length,
                        void* const destination)
{
    devMemFd = sys->open(devMemPath.c_str(), O_RDONLY);
    if (devMemFd < 0)
    {
        return false;
    }

    /* Map based on aligned addresses - behind the scenes. */
    const std::size_t alignedDiff = offset % sys->getpagesize();
    const std::size_t alignedOffset = offset - alignedDiff;
    const std::size_t alignedSize = length + alignedDiff;

    // addr, length, prot, flags, fd, offset
    devMemMapped = sys->mmap(0, alignedSize, PROT_READ, MAP_SHARED, devMemFd,
                             alignedOffset);
    if (devMemMapped == MAP_FAILED)
    {
        std::fprintf(stderr, "Failed to mmap at offset: 0x%zx, length: %zu\n",
                     offset, length);
        sys->close(devMemFd);
        return false;
    }

    void* alignedSource = static_cast<std::uint8_t*>(devMemMapped) +
                          alignedDiff;

    /* Copy the bytes. */
    std::memcpy(destination, alignedSource, length);

    /* Close the map between reads for now. */
    sys->munmap(devMemMapped, length);
    sys->close(devMemFd);

    return true;
}

bool DevMemDevice::write(const std::size_t offset, const std::size_t length,
                         const void* const source)
{
    devMemFd = sys->open(devMemPath.c_str(), O_RDWR);
    if (devMemFd < 0)
    {
        std::fprintf(stderr, "Failed to open /dev/mem for writing\n");
        return false;
    }

    /* Map based on aligned addresses - behind the scenes. */
    const std::size_t alignedDiff = offset % sys->getpagesize();
    const std::size_t alignedOffset = offset - alignedDiff;
    const std::size_t alignedSize = length + alignedDiff;

    // addr, length, prot, flags, fd, offset
    devMemMapped = sys->mmap(0, alignedSize, PROT_WRITE, MAP_SHARED, devMemFd,
                             alignedOffset);

    if (devMemMapped == MAP_FAILED)
    {
        std::fprintf(stderr, "Failed to mmap at offset: 0x%zx, length: %zu\n",
                     offset, length);
        sys->close(devMemFd);
        return false;
    }

    void* alignedDestination = static_cast<std::uint8_t*>(devMemMapped) +
                               alignedDiff;

    /* Copy the bytes. */
    std::memcpy(alignedDestination, source, length);

    /* Close the map between writes for now. */
    sys->munmap(devMemMapped, length);
    sys->close(devMemFd);

    return true;
}

PpcMemDevice::~PpcMemDevice()
{
    // Attempt to close in case reads or writes didn't close themselves
    close();
}

void PpcMemDevice::close()
{
    if (ppcMemFd >= 0)
    {
        sys->close(ppcMemFd);
        ppcMemFd = -1;
    }
}

bool PpcMemDevice::read(const std::size_t offset, const std::size_t length,
                        void* const destination)
{
    ppcMemFd = sys->open(ppcMemPath.c_str(), O_RDWR);
    if (ppcMemFd < 0)
    {
        std::fprintf(stderr, "Failed to open PPC LPC access path: %s",
                     ppcMemPath.c_str());
        return false;
    }

    int ret = sys->pread(ppcMemFd, destination, length, offset);
    if (ret < 0)
    {
        std::fprintf(stderr, "IO read failed at offset: 0x%zx, length: %zu\n",
                     offset, length);
        close();
        return false;
    }

    close();
    return true;
}

bool PpcMemDevice::write(const std::size_t offset, const std::size_t length,
                         const void* const source)
{
    ppcMemFd = sys->open(ppcMemPath.c_str(), O_RDWR);
    if (ppcMemFd < 0)
    {
        std::fprintf(stderr, "Failed to open PPC LPC access path: %s",
                     ppcMemPath.c_str());
        return false;
    }

    ssize_t ret = sys->pwrite(ppcMemFd, source, length, offset);
    if (ret < 0)
    {
        std::fprintf(stderr, "IO write failed at offset: 0x%zx, length: %zu\n",
                     offset, length);
        close();
        return false;
    }

    close();
    return true;
}

} // namespace host_tool
