/****************************************************************************
 * This file is part of the project AqHome.
 * AqHome (c) by 2026 Martin Preuss, all rights reserved.
 *
 * The license for this file can be found in the file COPYING which you
 * should have received along with this file.
 ****************************************************************************/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif



#include "aqhome/aqhome.h"
#include "aqhome/msg/node/m_time.h"
#include "aqhome/msg/node/m_node.h"

#include <gwenhywfar/debug.h>
#include <gwenhywfar/endianfns.h>



#define AQH_MSG_OFFS_TIME_UID          0  /* 4 bytes */
#define AQH_MSG_OFFS_TIME_MSGID        4  /* 2 bytes */
#define AQH_MSG_OFFS_TIME_YEAR         6  /* 2 bytes */
#define AQH_MSG_OFFS_TIME_MONTH        8  /* 1 byte */
#define AQH_MSG_OFFS_TIME_DAYOFMONTH   9  /* 1 byte */
#define AQH_MSG_OFFS_TIME_DAYOFWEEK   10  /* 1 byte */
#define AQH_MSG_OFFS_TIME_HOUR        11  /* 1 byte */
#define AQH_MSG_OFFS_TIME_MINUTE      12  /* 1 byte */
#define AQH_MSG_OFFS_TIME_SECOND      13  /* 1 byte */



AQH_MESSAGE *AQH_TimeMessage_new(uint8_t destAddr, uint8_t srcAddr, uint8_t code, uint16_t msgId, const GWEN_TIMESTAMP *ts)
{
  uint8_t payload[14];
  uint8_t *ptr;
  int i;

  ptr=payload;
  *(ptr++)=0;                     /* uid (empty) */
  *(ptr++)=0;
  *(ptr++)=0;
  *(ptr++)=0;

  *(ptr++)=msgId & 0xff;          /* msgid */
  *(ptr++)=(msgId>>8) & 0xff;

  i=GWEN_Timestamp_GetYear(ts);   /* year */
  *(ptr++)=i & 0xff;
  *(ptr++)=(i>>8) & 0xff;

  *(ptr++)=GWEN_Timestamp_GetMonth(ts) & 0xff;   /* month */
  *(ptr++)=GWEN_Timestamp_GetDay(ts) & 0xff;     /* day of month */
  *(ptr++)=((GWEN_Timestamp_GetWeekDay(ts)+1) & 0xff); /* day of week */
  *(ptr++)=GWEN_Timestamp_GetHour(ts) & 0xff;    /* hour */
  *(ptr++)=GWEN_Timestamp_GetMinute(ts) & 0xff;  /* minute */
  *(ptr++)=GWEN_Timestamp_GetSecond(ts) & 0xff;  /* second */

  return AQH_NodeMessage_new(destAddr, srcAddr, code, sizeof(payload), payload);
}



uint32_t AQH_TimeMessage_GetUid(const AQH_MESSAGE *msg)
{
  return AQH_Message_ReadUint32At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_TIME_UID, 0);
}



uint16_t AQH_TimeMessage_GetMsgId(const AQH_MESSAGE *msg)
{
  return AQH_Message_ReadUint16At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_TIME_MSGID, 0);
}



uint16_t AQH_TimeMessage_GetYear(const AQH_MESSAGE *msg)
{
  return AQH_Message_ReadUint16At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_TIME_YEAR, 0);
}



uint8_t AQH_TimeMessage_GetMonth(const AQH_MESSAGE *msg)
{
  return AQH_Message_ReadUint8At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_TIME_MONTH, 0);
}



uint8_t AQH_TimeMessage_GetDayOfMonth(const AQH_MESSAGE *msg)
{
  return AQH_Message_ReadUint8At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_TIME_DAYOFMONTH, 0);
}



uint8_t AQH_TimeMessage_GetDayOfWeek(const AQH_MESSAGE *msg)
{
  return AQH_Message_ReadUint8At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_TIME_DAYOFWEEK, 0);
}



uint8_t AQH_TimeMessage_GetHour(const AQH_MESSAGE *msg)
{
  return AQH_Message_ReadUint8At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_TIME_HOUR, 0);
}



uint8_t AQH_TimeMessage_GetMinute(const AQH_MESSAGE *msg)
{
  return AQH_Message_ReadUint8At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_TIME_MINUTE, 0);
}



uint8_t AQH_TimeMessage_GetSecond(const AQH_MESSAGE *msg)
{
  return AQH_Message_ReadUint8At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_TIME_SECOND, 0);
}



GWEN_TIMESTAMP *AQH_TimeMessage_GetTime(const AQH_MESSAGE *msg)
{
  return GWEN_Timestamp_new(AQH_TimeMessage_GetYear(msg),
			    AQH_TimeMessage_GetMonth(msg),
			    AQH_TimeMessage_GetDayOfMonth(msg),
			    AQH_TimeMessage_GetHour(msg),
			    AQH_TimeMessage_GetMinute(msg),
			    AQH_TimeMessage_GetSecond(msg));
}




void AQH_TimeMessage_DumpToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *dbuf, const char *sText)
{
  const char *sCmd;

  switch(AQH_NodeMessage_GetMsgType(msg)) {
  case AQH_MSG_TYPE_TIME_ANNOUNCE:   sCmd="announce"; break;
  case AQH_MSG_TYPE_TIME_REQSET:     sCmd="set"; break;
  case AQH_MSG_TYPE_TIME_RSPSET:     sCmd="ack"; break;
  default:                           sCmd="unknown"; break;
  }

  GWEN_Buffer_AppendArgs(dbuf,
			 "0x%02x->0x%02x: TIME(%s) %s (uid=0x%08x, msgId=%u, %04d/%02d/%02d-%02d:%02d:%02d (%d))\n",
			 AQH_NodeMessage_GetSourceAddress(msg),
			 AQH_NodeMessage_GetDestAddress(msg),
			 sCmd,
			 sText,
			 (unsigned int) AQH_TimeMessage_GetUid(msg),
			 (unsigned int)AQH_TimeMessage_GetMsgId(msg),
			 AQH_TimeMessage_GetYear(msg),
			 AQH_TimeMessage_GetMonth(msg),
			 AQH_TimeMessage_GetDayOfMonth(msg),
			 AQH_TimeMessage_GetHour(msg),
			 AQH_TimeMessage_GetMinute(msg),
			 AQH_TimeMessage_GetSecond(msg),
			 AQH_TimeMessage_GetDayOfWeek(msg));
}








