/****************************************************************************
 * 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 "aqhome/nodes/nodedb_p.h"

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




AQH_NODE_DB *AQH_NodeDb_new()
{
  AQH_NODE_DB *ndb;

  GWEN_NEW_OBJECT(AQH_NODE_DB, ndb);
  ndb->nodeList=AQH_NodeInfo_List_new();
  return ndb;
}



void AQH_NodeDb_free(AQH_NODE_DB *ndb)
{
  if (ndb) {
    AQH_NodeInfo_List_free(ndb->nodeList);
    GWEN_FREE_OBJECT(ndb);
  }
}



void AQH_NodeDb_SetModified(AQH_NODE_DB *ndb)
{
  ndb->modified=1;
}



void AQH_NodeDb_ClearModified(AQH_NODE_DB *ndb)
{
  ndb->modified=0;
}



int AQH_NodeDb_IsModified(const AQH_NODE_DB *ndb)
{
  return ndb->modified;
}



AQH_NODE_INFO_LIST *AQH_NodeDb_GetAllNodeInfos(AQH_NODE_DB *ndb)
{
  return ndb->nodeList;
}



int AQH_NodeDb_AddNodeInfo(AQH_NODE_DB *ndb, AQH_NODE_INFO *ni)
{
  uint32_t uid;
  uint8_t busAddr;

  uid=AQH_NodeInfo_GetUid(ni);
  if (uid==0) {
    DBG_ERROR(AQH_LOGDOMAIN, "Not adding node without UID");
    return GWEN_ERROR_INVALID;
  }
  if (AQH_NodeDb_GetNodeInfoByUid(ndb, uid)) {
    DBG_ERROR(AQH_LOGDOMAIN, "A node with the given UID \"%08x\" already exists", (unsigned int) uid);
    return GWEN_ERROR_INVALID;
  }

  busAddr=AQH_NodeInfo_GetBusAddress(ni);
#if 0
  if (busAddr==0) {
    DBG_ERROR(AQH_LOGDOMAIN, "Not adding node without BUSADDR");
    return GWEN_ERROR_INVALID;
  }
  if (AQH_NodeDb_GetNodeInfoByBusAddr(ndb, busAddr)) {
    DBG_ERROR(AQH_LOGDOMAIN, "A node with the given BUSADDR \"%02x\" already exists", busAddr);
    return GWEN_ERROR_INVALID;
  }
#endif

  DBG_NOTICE(AQH_LOGDOMAIN, "Adding node UID=%08x BUSADDR=%02x", (unsigned int) uid, busAddr);
  AQH_NodeInfo_List_Add(ni, ndb->nodeList);
  AQH_NodeDb_SetModified(ndb);
  return 0;
}



AQH_NODE_INFO *AQH_NodeDb_GetNodeInfoByBusAddr(AQH_NODE_DB *ndb, uint8_t busAddr)
{
  return AQH_NodeInfo_List_GetByBusAddress(ndb->nodeList, busAddr);
}



AQH_NODE_INFO *AQH_NodeDb_GetNodeInfoByUid(AQH_NODE_DB *ndb, uint32_t uid)
{
  return AQH_NodeInfo_List_GetByUid(ndb->nodeList, uid);
}



void AQH_NodeDb_toDb(AQH_NODE_DB *ndb, GWEN_DB_NODE *dbDatabase)
{
  if (ndb->nodeList) {
    AQH_NODE_INFO *ni;

    ni=AQH_NodeInfo_List_First(ndb->nodeList);
    while(ni) {
      GWEN_DB_NODE *dbNodeInfo;

      dbNodeInfo=GWEN_DB_Group_new("nodeInfo");
      AQH_NodeInfo_toDb(ni, dbNodeInfo);
      GWEN_DB_AddGroup(dbDatabase, dbNodeInfo);

      ni=AQH_NodeInfo_List_Next(ni);
    }
  }
}



void AQH_NodeDb_fromDb(AQH_NODE_DB *ndb, GWEN_DB_NODE *dbDatabase)
{
  GWEN_DB_NODE *dbNodeInfo;

  AQH_NodeInfo_List_Clear(ndb->nodeList);

  dbNodeInfo=GWEN_DB_FindFirstGroup(dbDatabase, "nodeinfo");
  while(dbNodeInfo) {
    AQH_NODE_INFO *ni;

    ni=AQH_NodeInfo_fromDb(dbNodeInfo);
    if (ni) {
      const char *deviceId;

      deviceId=AQH_NodeInfo_GetDeviceId(ni);
      DBG_NOTICE(AQH_LOGDOMAIN,
                 "Adding node %08x (%s, %04x:%02x:%04x)",
                 AQH_NodeInfo_GetUid(ni),
                 deviceId?deviceId:"<no device id>",
                 AQH_NodeInfo_GetManufacturer(ni),
                 AQH_NodeInfo_GetDeviceType(ni),
                 AQH_NodeInfo_GetDeviceVersion(ni));
      AQH_NodeInfo_List_Add(ni, ndb->nodeList);
    }

    dbNodeInfo=GWEN_DB_FindNextGroup(dbNodeInfo, "nodeinfo");
  }
  AQH_NodeDb_ClearModified(ndb);
}



