// Copyright 2024 Google LLC
//
// 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.

#include "message_spi.hpp"

#include <fcntl.h>
#include <unistd.h>

#include <cerrno>
#include <format>

namespace google
{
namespace hoth
{


MessageSPI::MessageSPI(const std::string& path, uint32_t mailbox_addr,
google::hoth::LibHothSpiDevIntf* libhoth_spi, const internal::Sys* sys) :
    mailbox_addr(mailbox_addr),
    dev(nullptr),
    libhoth_spi(libhoth_spi),
    sys(sys)
{
    struct libhoth_spi_device_init_options opts = {
      .path = &path[0],
      .mailbox = mailbox_addr,
      .bits = 0,
      .mode = 0,
      .speed = 0,
      .atomic = 0,
  };
    if (libhoth_spi->open(&opts, &dev) != LIBHOTH_OK) {
                throw internal::errnoException(
            std::format("Error opening Hoth interface "));
    }
    if (dev == nullptr) {
        throw internal::errnoException(
            std::format("Error opening Hoth interface \"{}\"", path));
    }
}

MessageSPI::~MessageSPI()
{
    if (dev != nullptr)
    {
        libhoth_spi->close(dev);
    }
}

void MessageSPI::send(const uint8_t* buf, size_t size, size_t seek)
{
    if (seek > size) {
        return;
    }
    ssize_t ret = -1;
    do
    {
        //ret = dev->send(fd, buf, size);
        ret = libhoth_spi->send(dev, buf+seek, size);
        // Retry if interrupted
    } while (ret < 0 && errno == EINTR);

    if (ret < 0)
    {
        throw internal::errnoException("Error writing to Hoth interface");
    }

    if (static_cast<size_t>(ret) != LIBHOTH_OK)
    {
        // Fail on incomplete writes because they can confuse Hoth
        throw std::runtime_error(std::format(
            "Tried to send message of size {} but could only send {} bytes",
            size, ret));
    }
}

void MessageSPI::recv(uint8_t* buf, size_t size, size_t seek)
{
    static uint8_t spidev_buf[LIBHOTH_MAILBOX_SIZE];
    static size_t spidev_buf_sz = 0;

    if (size + seek > LIBHOTH_MAILBOX_SIZE)
    {
        return;
    }

    if (spidev_buf_sz > 0)
    {
        memcpy(buf, spidev_buf+seek, size);
        spidev_buf_sz = 0;
        return;
    }

read_spidev:
    auto ret = libhoth_spi->recv(dev, spidev_buf, LIBHOTH_MAILBOX_SIZE, &spidev_buf_sz, 0);
    if (ret < 0)
    {
        if (errno == EINTR)
        {
            goto read_spidev; // interrupted; try again
        }

        throw internal::errnoException("Error reading from Hoth interface");
    }
    if (spidev_buf_sz == 0)
    {
        // EOF hit
        throw std::runtime_error("Hit EOF while expecting data");
    }
    memcpy(buf, spidev_buf, size);
}

} // namespace hoth

} // namespace google
