//{{copyright}}

//{{version}}

//{{license}}

#pragma once

#include "../HIDBus.h"
#include "../../../dateTime/FreeRTOS/timer.h"

#include <sdi_uToolBox/generic/FreeRTOS/mutex.h>
#include <sdi_uToolBox/generic/FreeRTOS/semaphore.h>

namespace sdi_uToolBox::stm32::comm::FreeRTOS
{
//--------------------------------------------------------------
class HIDBus : public comm::HIDBus
{
  public:
  using Mutex = generic::FreeRTOS::Mutex;
  using BinarySemaphore = generic::FreeRTOS::BinarySemaphore;

  public:
  HIDBus();     // Default constructor
  virtual ~HIDBus()                  = default;     // Default destructor
  HIDBus(const HIDBus &)            = delete;      // Copy constructor
  HIDBus(HIDBus &&)                 = delete;      // Move constructor
  HIDBus &operator=(const HIDBus &) = delete;      // Copy assignment operator
  HIDBus &operator=(HIDBus &&)      = delete;      // Move assignment operator

  ReturnStatus open() override;      // Open UART bus
  ReturnStatus close() override;     // Close UART bus

  ReturnType write(WriteBuf buf, Timeout timeout) const override;     // Write data to UART device
  ReturnType read(ReadBuf buf, Timeout timeout) const override;       // Read data from UART device

  void rxCompleteCallback(std::span<const uint8_t> buf) override;

  protected:
  mutable Mutex m_mtx;
  mutable BinarySemaphore m_semaphore{false};
  dateTime::FreeRTOS::Timer m_timer;

};
//--------------------------------------------------------------
inline HIDBus::HIDBus()
{
  m_genericTimer = &m_timer;
}
//--------------------------------------------------------------
/* Open UART bus */
inline ReturnStatus HIDBus::open()
{
  std::scoped_lock lock(m_mtx);
  return comm::HIDBus::open();
}
//--------------------------------------------------------------
/* Close UART bus */
inline ReturnStatus HIDBus::close()
{
  std::scoped_lock lock(m_mtx);
  return comm::HIDBus::close();
}
//--------------------------------------------------------------
/* Write data to UART device */
inline HIDBus::ReturnType HIDBus::write(const WriteBuf buf, const Timeout timeout) const
{
  std::scoped_lock lock(m_mtx);
  return comm::HIDBus::write(buf, timeout);
}
//--------------------------------------------------------------
/* Read data from UART device */
inline HIDBus::ReturnType HIDBus::read(const ReadBuf buf, const Timeout timeout) const
{
  if (!m_semaphore.take(timeout))
    return std::unexpected(ReturnStatus::Timeout);

  std::scoped_lock lock(m_mtx);
  return comm::HIDBus::read(buf, std::chrono::milliseconds(0));
}
//--------------------------------------------------------------
 inline void HIDBus::rxCompleteCallback(std::span<const uint8_t> buf)
{
  comm::HIDBus::rxCompleteCallback(buf);
  (void)m_semaphore.giveFromISR();
}
//--------------------------------------------------------------
}     // namespace sdi_uToolBox::stm32::comm
