/****************************************************************************
 * This file is part of the project AqHome.
 * AqHome (c) by 2024 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 "./port_p.h"
#include "aqhome-react/types/dataobject.h"

#include <gwenhywfar/debug.h>



GWEN_LIST_FUNCTIONS(AQHREACT_PORT, AQHREACT_Port)


AQHREACT_PORT *AQHREACT_Port_new()
{
  AQHREACT_PORT *port;

  GWEN_NEW_OBJECT(AQHREACT_PORT, port);
  GWEN_LIST_INIT(AQHREACT_PORT, port);
  port->linkList=AQHREACT_Link_List_new();
  return port;
}



AQHREACT_PORT *AQHREACT_Port_dup(const AQHREACT_PORT *srcPort)
{
  if (srcPort) {
    AQHREACT_PORT *newPort;

    newPort=AQHREACT_Port_new();
    AQHREACT_Port_SetName(newPort, srcPort->name);
    newPort->idForUnit=srcPort->idForUnit;
    AQHREACT_Port_SetDescription(newPort, srcPort->description);
    newPort->flags=srcPort->flags;
    newPort->dataType=srcPort->dataType;
    /* don't copy current dataObject */
    /* don't copy current links */
    return newPort;
  }
  return NULL;
}



void AQHREACT_Port_free(AQHREACT_PORT *port)
{
  if (port) {
    GWEN_LIST_FINI(AQHREACT_PORT, port);
    AQHREACT_DataObject_free(port->currentDataObject);
    AQHREACT_Link_List_free(port->linkList);
    free(port->name);
    free(port->description);
    GWEN_FREE_OBJECT(port);
  }
}



const char *AQHREACT_Port_GetName(const AQHREACT_PORT *port)
{
  return port?port->name:NULL;
}



void AQHREACT_Port_SetName(AQHREACT_PORT *port, const char *s)
{
  if (port) {
    free(port->name);
    port->name=s?strdup(s):NULL;
  }
}



int AQHREACT_Port_GetIdForUnit(const AQHREACT_PORT *port)
{
  return port?port->idForUnit:0;
}



void AQHREACT_Port_SetIdForUnit(AQHREACT_PORT *port, int i)
{
  if (port)
    port->idForUnit=i;
}



const char *AQHREACT_Port_GetDescription(const AQHREACT_PORT *port)
{
  return port?port->description:NULL;
}



void AQHREACT_Port_SetDescription(AQHREACT_PORT *port, const char *s)
{
  if (port) {
    free(port->description);
    port->description=s?strdup(s):NULL;
  }
}



uint32_t AQHREACT_Port_GetFlags(const AQHREACT_PORT *port)
{
  return port?port->flags:0;
}



void AQHREACT_Port_SetFlags(AQHREACT_PORT *port, uint32_t f)
{
  if (port)
    port->flags=f;
}



void AQHREACT_Port_AddFlags(AQHREACT_PORT *port, uint32_t f)
{
  if (port)
    port->flags|=f;
}



void AQHREACT_Port_SubFlags(AQHREACT_PORT *port, uint32_t f)
{
  if (port)
    port->flags&=~f;
}



int AQHREACT_Port_GetDataType(const AQHREACT_PORT *port)
{
  return port?port->dataType:AQHREACT_DATAOBJECTTYPE_UNKNOWN;
}



void AQHREACT_Port_SetDataType(AQHREACT_PORT *port, int i)
{
  if (port)
    port->dataType=i;
}



AQHREACT_DATAOBJECT *AQHREACT_Port_GetCurrentDataObject(const AQHREACT_PORT *port)
{
  return port?port->currentDataObject:NULL;
}



void AQHREACT_Port_SetCurrentDataObject(AQHREACT_PORT *port, AQHREACT_DATAOBJECT *dataObject)
{
  if (port){
    AQHREACT_DataObject_free(port->currentDataObject);
    port->currentDataObject=dataObject;
  }
}



AQHREACT_LINK_LIST *AQHREACT_Port_GetLinkList(const AQHREACT_PORT *port)
{
  return port?port->linkList:NULL;
}



void AQHREACT_Port_AddLink(AQHREACT_PORT *port, AQHREACT_LINK *lnk)
{
  if (port)
    AQHREACT_Link_List_Add(lnk, port->linkList);
}



void AQHREACT_Port_SendData(const AQHREACT_PORT *port, const AQHREACT_DATAOBJECT *dataObject)
{
  AQHREACT_LINK_LIST *linkList;
  
  linkList=AQHREACT_Port_GetLinkList(port);
  if (linkList) {
    AQHREACT_LINK *lnk;
  
    lnk=AQHREACT_Link_List_First(linkList);
    while(lnk) {
      AQHREACT_UNIT *targetUnit;
      AQHREACT_PORT *targetPort;

      targetUnit=AQHREACT_Link_GetTargetUnit(lnk);
      targetPort=AQHREACT_Link_GetTargetPort(lnk);
      if (targetUnit && targetPort) {
        DBG_DEBUG(NULL, "%s: Sending data to %s:%s",
                  AQHREACT_Port_GetName(port), AQHREACT_Unit_GetId(targetUnit), AQHREACT_Port_GetName(targetPort));
        AQHREACT_Unit_InputData(targetUnit, targetPort, dataObject);
      }
      lnk=AQHREACT_Link_List_Next(lnk);
    } /* while */
  } /* if linkList */
}



AQHREACT_PORT *AQHREACT_Port_List_GetByName(const AQHREACT_PORT_LIST *portList, const char *name)
{
  if (portList && name) {
    AQHREACT_PORT *port;

    port=AQHREACT_Port_List_First(portList);
    while(port) {
      const char *s;

      s=AQHREACT_Port_GetName(port);
      if (s && strcasecmp(s, name)==0)
        return port;
      port=AQHREACT_Port_List_Next(port);
    }
  }
  return NULL;
}



AQHREACT_PORT *AQHREACT_Port_List_GetByIdForUnit(const AQHREACT_PORT_LIST *portList, int id)
{
  if (portList) {
    AQHREACT_PORT *port;

    port=AQHREACT_Port_List_First(portList);
    while(port) {
      if (id==AQHREACT_Port_GetIdForUnit(port))
        return port;
      port=AQHREACT_Port_List_Next(port);
    }
  }
  return NULL;
}



void AQHREACT_Port_Dump(const AQHREACT_PORT *port, GWEN_BUFFER *buf, int indent)
{
  if (port && buf) {
    if (indent)
      GWEN_Buffer_FillWithBytes(buf, ' ', indent);
    GWEN_Buffer_AppendArgs(buf, "- \"%s\"[%d] (%s, %08x)\n",
                           (port->name)?(port->name):"<no name>",
                           port->idForUnit,
                           AQHREACT_DataObjectType_toString(port->dataType),
                           port->flags);
    if (port->linkList && AQHREACT_Link_List_GetCount(port->linkList))
      AQHREACT_Link_List_Dump(port->linkList, buf, indent+2, "Link List:");
  }
}



void AQHREACT_Port_List_Dump(const AQHREACT_PORT_LIST *portList, GWEN_BUFFER *buf, int indent, const char *title)
{
  if (portList && buf) {
    const AQHREACT_PORT *port;

    if (indent)
      GWEN_Buffer_FillWithBytes(buf, ' ', indent);
    GWEN_Buffer_AppendArgs(buf, "%s\n", (title && *title)?title:"Port List:\n");

    port=AQHREACT_Port_List_First(portList);
    while(port) {
      AQHREACT_Port_Dump(port, buf, indent+2);
      port=AQHREACT_Port_List_Next(port);
    }
  }
}










