#ifndef LEPTO_CAN_MESSAGE_HPP
#define LEPTO_CAN_MESSAGE_HPP
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------


#include <stdint.h>
#include <string.h>        // memcpy
#include <lepto/time.h>    // timestamp_t

#if ! defined( STM32 )
#include <QDateTime>
#endif

#if __GNUC__ < 12
   //#define constexpr_nobug
#elif __GNUC__ == 12 && (__GNUC_MINOR__ < 3 )
   //#define constexpr_nobug
#else
   //#define constexpr_nobug
   // constexpr
#endif

#if defined( STM32 )
   #define constexpr_st constexpr
#else
   #define constexpr_st
#endif

enum ECanMessageId
{
   eCanMessageIdNull=0,

   eCanMessageIdSetTime,
   eCanMessageIdSendTemperature,
   eCanMessageIdScan,

   eCanMessageIdMax
};

extern const char *canMessageIdCodeStrings[];

#if ! defined( STM32 )
// extern int globalCanMessage_cnt;
#endif

typedef uint32_t canId_t;


/// \brief  simple can message/package/telegramm
///
///         It's a good idea to keep data "unsigned"
class CCanMessage
{
   private:
      canId_t m_id;
      int m_len;
      //int m_foo;

#if defined LEPTO_CAN_ORGLEN
      bool originExtended;
#endif

#if ! defined( STM32 )
      int m_cnt=0;
      timestamp_t timeStamp;
#endif

   protected:

      //uint32_t *m_data32=(uint32_t *)&m_data;
      unsigned char m_data[8];
   private:
      //int8_t m_len;
      //int m_len;


   public:

      //constexpr_nobug
      constexpr CCanMessage()
            :m_id(0)
            ,m_len(0)
            #if defined LEPTO_CAN_ORGLEN
            ,originExtended(false)
            #endif
            #if ! defined( STM32 )
            ,m_cnt(0)
            ,timeStamp(0)
            #endif
            ,m_data{0}
      {
      }
       
      /// \brief  Le contructeur
      //constexpr_nobug
      constexpr CCanMessage(int id)
            :m_id(id)
            ,m_len(0)
            #if defined LEPTO_CAN_ORGLEN
            ,originExtended(false)
            #endif
            #if ! defined( STM32 )
            ,m_cnt(0)
            ,timeStamp(0)
            #endif
            ,m_data{0}
      {
      }
      
      //constexpr_nobug
      constexpr_st CCanMessage(int id, int len, const void *data)
         :m_id(id)
         #if ! defined( STM32 )
            //,m_cnt(globalCanMessage_cnt++)
         #endif
         ,m_len{len}
         #if defined LEPTO_CAN_ORGLEN
         ,originExtended(false)
         #endif
   
         #if ! defined( STM32 )
         //,timeStamp(CTime::currentTimeStamp())
         ,timeStamp( QDateTime::currentSecsSinceEpoch() )
         #endif
         {
            if(m_len)
            {
               memcpy(m_data, data, m_len);
            }
         }
      
      /*
      CCanMessage( const CCanMessage& ref )
      {
         m_id=ref.m_id;
         m_len=ref.m_len;
         originExtended=ref.originExtended;
         m_data32[0]=ref.m_data32[0];
         m_data32[1]=ref.m_data32[1];
      }
      */
      void setId(canId_t id)
      {
         m_id=id;
         return;
      }
      constexpr canId_t getId( ) const
      {
         return(m_id);
      }
      constexpr const unsigned char *getData( ) const
         {return(m_data);};
      unsigned char *getData( )
         {return(m_data);};

      constexpr int getLen( ) const
      {
         return(m_len);
      };
      constexpr void setLen( int length )
      {
         m_len=length;
         return;
      };

      void setData(int len, const unsigned char *data)
      {
         m_len=len;
         memcpy(m_data, data, m_len > 8 ? 8 : m_len);
         //m_data32[0]=((uint32_t *)data)[0];
         //m_data32[1]=((uint32_t *)data)[1];
         return;
      }

      CCanMessage &operator <<(char byte);
      CCanMessage &operator <<(int16_t value);
      ~CCanMessage();
      unsigned char operator [](int index)
      {
         return(m_data[index]);
      }

      unsigned char at(int index)
      {
         return(m_data[index]);
      }

      bool isExtended() const
      {
         // 2^11 == 1<<11
         return( (m_id >= (1 << 11) ) ? true : false );
      }

      #if defined LEPTO_CAN_ORGLEN

      bool isOriginExtended() const
      {
         return(originExtended);
      }
      void setOriginExtended(bool _originExtended)
      {
         originExtended=_originExtended;
         return;
      }

      #endif

      const char *getIdString() const;
#if ! defined( STM32 )
      timestamp_t getTimeStamp() const
      {
         return(timeStamp);
      }

      int getCount() const
      {
         return(m_cnt);
      }
#endif
      int convertToAscii(char *dest);
      bool fromAscii(const char *src);
};


//---fin-----------------------------------------------------------------------
#endif // ? ! LEPTO_CAN_MESSAGE_HPP
