/****************************************************************************
 * This file is part of the project AqHome.
 * AqHome (c) by 2025 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/msg/mqtt/m_mqtt_publish.h"
#include "aqhome/msg/mqtt/m_mqtt.h"

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



/* ------------------------------------------------------------------------------------------------
 * implementation
 * ------------------------------------------------------------------------------------------------
 */
AQH_MESSAGE *AQH_MqttMessagePublish_new(uint8_t flags, uint16_t packetId,
                                        const char *sTopic, const uint8_t *messagePtr, uint32_t messageLen)
{
  AQH_MESSAGE *msg;
  GWEN_BUFFER *buf;

  buf=GWEN_Buffer_new(0, 64, 0, 1);
  AQH_MqttMessage_AppendStringWithLenToBuffer(buf, sTopic?sTopic:"");
  if (flags & (AQH_MQTTMSG_FLAGS_QOS2 | AQH_MQTTMSG_FLAGS_QOS1)) {
    GWEN_Buffer_AppendByte(buf, (packetId>>8) & 0xff);
    GWEN_Buffer_AppendByte(buf, packetId & 0xff);
  }

  /* payload */
  if (messagePtr && messageLen)
    GWEN_Buffer_AppendBytes(buf, (const char*) messagePtr, messageLen);

  msg=AQH_MqttMessage_new(AQH_MQTTMSG_MSGTYPE_PUBLISH | flags,
                          GWEN_Buffer_GetUsedBytes(buf),
                          (const uint8_t*) GWEN_Buffer_GetStart(buf));
  GWEN_Buffer_free(buf);
  return msg;
}



int AQH_MqttMessagePublish_GetPacketId(const AQH_MESSAGE *msg)
{
  if (AQH_MqttMessage_GetTypeAndFlags(msg) & (AQH_MQTTMSG_FLAGS_QOS2 | AQH_MQTTMSG_FLAGS_QOS1)) {
    int idx;

    idx=AQH_MqttMessage_GetOffsetOfPayload(msg);
    if (idx>0) {
      int len;

      len=(int)AQH_Message_GetUsedSize(msg)-idx;
      if (len>1) {
        uint8_t *ptr;
        int rv;

        ptr=AQH_Message_GetMsgPointer(msg);
        rv=AQH_MqttMessage_SkipStringAt(ptr, len);
        if (rv<0) {
          DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
          return rv;
        }
        idx+=rv;
        ptr+=rv;
        len-=rv;
        if (idx<len)
          return (ptr[0]<<8)+ptr[1];
      }
    }
  }
  return 0;
}



char *AQH_MqttMessagePublish_ExtractTopic(const AQH_MESSAGE *msg)
{
  int idx;

  idx=AQH_MqttMessage_GetOffsetOfPayload(msg);
  if (idx>0) {
    uint8_t *ptr;
    int len;

    ptr=AQH_Message_GetMsgPointer(msg)+idx;
    len=(int)AQH_Message_GetUsedSize(msg)-idx;
    DBG_INFO(AQH_LOGDOMAIN, "Extracting string from %d (remaining len=%d)", idx, len);
    if (len>1)
      return AQH_MqttMessage_ExtractStringAt(ptr, len);
  }
  return NULL;
}



char *AQH_MqttMessagePublish_ExtractValue(const AQH_MESSAGE *msg)
{
  int idx;

  idx=AQH_MqttMessage_GetOffsetOfPayload(msg);
  if (idx>0) {
    uint8_t *ptr;
    int len;

    ptr=AQH_Message_GetMsgPointer(msg)+idx;
    len=(int)AQH_Message_GetUsedSize(msg)-idx;
    if (len>1) {
      int rv;

      rv=AQH_MqttMessage_SkipStringAt(ptr, len);
      if (rv<0) {
        DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
        return NULL;
      }
      ptr+=rv;
      len-=rv;
      if (AQH_MqttMessage_GetTypeAndFlags(msg) & (AQH_MQTTMSG_FLAGS_QOS2 | AQH_MQTTMSG_FLAGS_QOS1)) {
        ptr+=2;
        len-=2;
      }
      if (len>0) {
        char *result;

        result=(char*) malloc(len+1);
        if (result) {
          memmove(result, ptr, len);
          result[len]=0;
          return result;
        }
      }
    }
  }
  return NULL;
}



