/****************************************************************************
 * This file is part of the project AqHome.
 * AqHome (c) by 2023 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 "msg_ipc_tag16_p.h"

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


/* ------------------------------------------------------------------------------------------------
 * forward declarations
 * ------------------------------------------------------------------------------------------------
 */

static void GWENHYWFAR_CB _freeData(void *bp, void *p);
static GWEN_TAG16_LIST *_parseTags(const GWEN_MSG *msg, int doCopy);



/* ------------------------------------------------------------------------------------------------
 * implementations
 * ------------------------------------------------------------------------------------------------
 */

GWEN_INHERIT(GWEN_MSG, AQH_MSG_IPC_TAG16);



GWEN_MSG *AQH_Tag16IpcMsg_new(uint8_t protoId, uint8_t protoVer, uint16_t code, uint32_t payloadLen, const uint8_t *payload)
{
  GWEN_MSG *msg;

  msg=GWEN_IpcMsg_new(protoId, protoVer, code, payloadLen, payload);
  AQH_Tag16IpcMsg_Extend(msg);
  return msg;
}



void AQH_Tag16IpcMsg_Extend(GWEN_MSG *msg)
{
  AQH_MSG_IPC_TAG16 *xmsg;

  GWEN_NEW_OBJECT(AQH_MSG_IPC_TAG16, xmsg);
  GWEN_INHERIT_SETDATA(GWEN_MSG, AQH_MSG_IPC_TAG16, msg, xmsg, _freeData);
}




void _freeData(void *bp, void *p)
{
  AQH_MSG_IPC_TAG16 *xmsg;

  xmsg=(AQH_MSG_IPC_TAG16*) p;
  GWEN_Tag16_List_free(xmsg->tagList);
  GWEN_FREE_OBJECT(xmsg);
}



GWEN_TAG16_LIST *AQH_Tag16IpcMsg_GetTags(const GWEN_MSG *msg)
{
  if (msg) {
    AQH_MSG_IPC_TAG16 *xmsg;

    xmsg=GWEN_INHERIT_GETDATA(GWEN_MSG, AQH_MSG_IPC_TAG16, msg);
    if (xmsg) {
      return xmsg->tagList;
    }
    else {
      DBG_INFO(AQH_LOGDOMAIN, "Not a Tag16IpcMsg message");
      return NULL;
    }
  }
  else {
    DBG_INFO(AQH_LOGDOMAIN, "NULLPOINTER");
    return NULL;
  }
}



void AQH_Tag16IpcMsg_ReadTags(GWEN_MSG *msg, int doCopy)
{
  if (msg) {
    AQH_MSG_IPC_TAG16 *xmsg;

    xmsg=GWEN_INHERIT_GETDATA(GWEN_MSG, AQH_MSG_IPC_TAG16, msg);
    if (xmsg) {
      if (xmsg->tagList) {
        DBG_INFO(AQH_LOGDOMAIN, "Tags already parsed");
      }
      else {
        xmsg->tagList=_parseTags(msg, doCopy);
        if (xmsg->tagList==NULL) {
          DBG_INFO(AQH_LOGDOMAIN, "No tags received");
        }
      }
    }
    else {
      DBG_INFO(AQH_LOGDOMAIN, "Not a Tag16IpcMsg message");
    }
  }
  else {
    DBG_INFO(AQH_LOGDOMAIN, "NULLPOINTER");
  }
}



void AQH_Tag16IpcMsg_ExtendAndParse(GWEN_MSG *msg, int doCopy)
{
  if (!(GWEN_INHERIT_ISOFTYPE(GWEN_MSG, AQH_MSG_IPC_TAG16, msg)))
    AQH_Tag16IpcMsg_Extend(msg);
  AQH_Tag16IpcMsg_ReadTags(msg, doCopy);
}



char *AQH_Tag16IpcMsg_GetTagDataAsNewString(const GWEN_MSG *msg, unsigned int tagType, const char *defaultValue)
{
  if (msg) {
    AQH_MSG_IPC_TAG16 *xmsg;

    xmsg=GWEN_INHERIT_GETDATA(GWEN_MSG, AQH_MSG_IPC_TAG16, msg);
    if (xmsg && xmsg->tagList) {
      const GWEN_TAG16 *tag;

      tag=GWEN_Tag16_List_FindFirstByTagType(xmsg->tagList, tagType);
      if (tag)
        return GWEN_Tag16_GetTagDataAsNewString(tag, defaultValue);
    }
  }
  return defaultValue?strdup(defaultValue):NULL;
}



uint32_t AQH_Tag16IpcMsg_GetTagDataAsUint32(const GWEN_MSG *msg, unsigned int tagType, uint32_t defaultValue)
{
  if (msg) {
    AQH_MSG_IPC_TAG16 *xmsg;

    xmsg=GWEN_INHERIT_GETDATA(GWEN_MSG, AQH_MSG_IPC_TAG16, msg);
    if (xmsg && xmsg->tagList) {
      const GWEN_TAG16 *tag;

      tag=GWEN_Tag16_List_FindFirstByTagType(xmsg->tagList, tagType);
      return tag?GWEN_Tag16_GetTagDataAsUint32(tag, defaultValue):defaultValue;
    }
  }
  return defaultValue;
}



uint64_t AQH_Tag16IpcMsg_GetTagDataAsUint64(const GWEN_MSG *msg, unsigned int tagType, uint64_t defaultValue)
{
  if (msg) {
    AQH_MSG_IPC_TAG16 *xmsg;

    xmsg=GWEN_INHERIT_GETDATA(GWEN_MSG, AQH_MSG_IPC_TAG16, msg);
    if (xmsg && xmsg->tagList) {
      const GWEN_TAG16 *tag;

      tag=GWEN_Tag16_List_FindFirstByTagType(xmsg->tagList, tagType);
      return tag?GWEN_Tag16_GetTagDataAsUint64(tag, defaultValue):defaultValue;
    }
  }
  return defaultValue;
}



const GWEN_TAG16 *AQH_Tag16IpcMsg_FindFirstTagByType(const GWEN_MSG *msg, unsigned int tagType)
{
  if (msg) {
    AQH_MSG_IPC_TAG16 *xmsg;

    xmsg=GWEN_INHERIT_GETDATA(GWEN_MSG, AQH_MSG_IPC_TAG16, msg);
    if (xmsg && xmsg->tagList)
      return GWEN_Tag16_List_FindFirstByTagType(xmsg->tagList, tagType);
  }
  return NULL;
}



GWEN_TAG16_LIST *AQH_Tag16IpcMsg_ParseTags(const GWEN_MSG *msg, int doCopy)
{
  return _parseTags(msg, doCopy);
}



GWEN_TAG16_LIST *_parseTags(const GWEN_MSG *msg, int doCopy)
{
  uint32_t msgSize;

  msgSize=GWEN_Msg_GetBytesInBuffer(msg);
  if (msgSize>GWEN_MSGIPC_OFFS_PAYLOAD) {
    const uint8_t *ptr;
    uint32_t payloadSize;

    ptr=GWEN_Msg_GetConstBuffer(msg)+GWEN_MSGIPC_OFFS_PAYLOAD;
    payloadSize=msgSize-GWEN_MSGIPC_OFFS_PAYLOAD;

    if (payloadSize) {
      GWEN_TAG16_LIST *tagList;

      tagList=GWEN_Tag16_List_fromBuffer(ptr, payloadSize, doCopy);
      if (tagList==NULL) {
        DBG_INFO(AQH_LOGDOMAIN, "Error reading tags from message");
        return NULL;
      }
      return tagList;
    }
  }

  return NULL;
}



void AQH_Tag16IpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
{
  if (GWEN_Msg_GetBytesInBuffer(msg)>=GWEN_MSGIPC_OFFS_PAYLOAD) {
    GWEN_Buffer_AppendArgs(dbuf,
                           "Tag16 (code=%d, proto=%d, proto version=%d)\n",
                           GWEN_IpcMsg_GetCode(msg),
                           GWEN_IpcMsg_GetProtoId(msg),
                           GWEN_IpcMsg_GetProtoVersion(msg));
  }
}







