// 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.

#pragma once

#include "message_intf.hpp"
#include "libhoth_spi.hpp"
#include "sys.hpp"
namespace google
{
namespace hoth
{

class MessageSPI : public MessageIntf
{
  public:
    explicit MessageSPI(const std::string& path, uint32_t mailbox_addr,
                        google::hoth::LibHothSpiDevIntf* libhoth_spi,
                         const internal::Sys* sys = &internal::sys_impl);
    ~MessageSPI() override;

    /* Delete the copy constructor and copy assignment operator because the fd
     * must be unique.
     *
     * TODO: switch to fd wrapper class once it's available upstream
     */
    MessageSPI(const MessageSPI& other) = delete;
    MessageSPI& operator=(const MessageSPI& other) = delete;

    void send(const uint8_t* buf, size_t size, size_t seek) override;
    void recv(uint8_t* buf, size_t size, size_t seek) override;

  private:
    int fd;
    uint32_t mailbox_addr;
    google::hoth::LibHothSpiDevIntf::device* dev;
    google::hoth::LibHothSpiDevIntf* libhoth_spi;
    const internal::Sys* sys;
};

} // namespace hoth

} // namespace google
