/*
{{copyright}} 
*/

/*
{{version}} 
*/

/*
{{license}} 
*/

#pragma once

#include "../I2CBus.h"

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

namespace sdi_uToolBox::stm32::comm::FreeRTOS
{
//--------------------------------------------------------------
class I2CBus : public stm32::comm::I2CBus
{
  public:
  using RecursiveMutex = generic::FreeRTOS::RecursiveMutex;

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

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

  std::unique_lock<RecursiveMutex> getLock() const;     // Get unique lock for the bus

  ReturnType   write(uint8_t address, WriteBuf buf, Timeout timeout) const override;     // Write data to I2C device
  ReturnType   read(uint8_t address, ReadBuf buf, Timeout timeout) const override;       // Read data from I2C device
  ReturnStatus isDeviceReady(uint8_t address) const override;                            // Check if I2C device is ready

  protected:
  mutable RecursiveMutex m_mtx;     // Mutex for thread safety
};
//--------------------------------------------------------------

//--------------------------------------------------------------
/* Open I2C bus */
inline ReturnStatus I2CBus::open()
{
  std::scoped_lock lock(m_mtx);
  return stm32::comm::I2CBus::open();
}
//--------------------------------------------------------------
/* Close I2C bus */
inline ReturnStatus I2CBus::close()
{
  std::scoped_lock lock(m_mtx);
  return stm32::comm::I2CBus::close();
}
//--------------------------------------------------------------
/* Get unique lock for the bus */
inline std::unique_lock<I2CBus::RecursiveMutex> I2CBus::getLock() const
{
  return std::unique_lock(m_mtx);
}
//--------------------------------------------------------------
/* Write data to I2C device */
inline I2CBus::ReturnType I2CBus::write(const uint8_t address, const WriteBuf buf, const Timeout timeout) const
{
  std::scoped_lock lock(m_mtx);
  return stm32::comm::I2CBus::write(address, buf, timeout);
}
//--------------------------------------------------------------
/* Read data from I2C device */
inline I2CBus::ReturnType I2CBus::read(const uint8_t address, const ReadBuf buf, const Timeout timeout) const
{
  std::scoped_lock lock(m_mtx);
  return stm32::comm::I2CBus::read(address, buf, timeout);
}
//--------------------------------------------------------------
/* Check if I2C device is ready */
inline ReturnStatus I2CBus::isDeviceReady(const uint8_t address) const
{
  std::scoped_lock lock(m_mtx);
  return stm32::comm::I2CBus::isDeviceReady(address);
}
//--------------------------------------------------------------
}     // namespace sdi_uToolBox::stm32::comm::FreeRTOS
