/****************************************************************************
 * 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 "./aqhome_react_p.h"
#include "./net_read.h"
#include "aqhome-react/units/u_logical.h"
#include "aqhome-react/units/u_valuefilter.h"
#include "aqhome-react/units/u_valueset.h"
#include "aqhome-react/units/u_stabilize.h"
#include "aqhome-react/units/u_lowpass.h"
#include "aqhome-react/units/u_highpass.h"
#include "aqhome-react/units/u_zeroposnegstring.h"


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



AQHOME_REACT *AqHomeReact_new()
{
  AQHOME_REACT *aqh;

  GWEN_NEW_OBJECT(AQHOME_REACT, aqh);
  aqh->unitList=AQHREACT_Unit_List_new();

  return aqh;
}



void AqHomeReact_free(AQHOME_REACT *aqh)
{
  if (aqh) {
    AQHREACT_Unit_List_free(aqh->unitList);
    GWEN_MsgEndpoint_free(aqh->brokerEndpoint);
    GWEN_DB_Group_free(aqh->dbArgs);
    free(aqh->pidFile);

    GWEN_FREE_OBJECT(aqh);

  }
}



GWEN_MSG_ENDPOINT *AqHomeReact_GetBrokerEndpoint(const AQHOME_REACT *aqh)
{
  return aqh?(aqh->brokerEndpoint):NULL;
}



GWEN_DB_NODE *AqHomeReact_GetDbArgs(const AQHOME_REACT *aqh)
{
  return aqh?(aqh->dbArgs):NULL;
}



const char *AqHomeReact_GetPidFile(const AQHOME_REACT *aqh)
{
  return aqh?aqh->pidFile:NULL;
}



void AqHomeReact_SetPidFile(AQHOME_REACT *aqh, const char *s)
{
  if (aqh) {
    free(aqh->pidFile);
    aqh->pidFile=s?strdup(s):NULL;
  }
}



int AqHomeReact_GetTimeout(const AQHOME_REACT *aqh)
{
  return aqh?aqh->timeout:0;
}



time_t AqHomeReact_GetLatestNetworkFileTime(const AQHOME_REACT *aqh)
{
  return aqh?aqh->latestNetworkFileTime:0;
}



void AqHomeReact_SetLatestNetworkFileTime(AQHOME_REACT *aqh, time_t t)
{
  if (aqh)
    aqh->latestNetworkFileTime=t;
}



AQHREACT_UNIT *AqHomeReact_GetTimerUnit(const AQHOME_REACT *aqh)
{
  return aqh?aqh->timerUnit:NULL;
}



AQHREACT_UNIT *AqHomeReact_GetVarChangeUnit(const AQHOME_REACT *aqh)
{
  return aqh?aqh->varChangeUnit:NULL;
}



AQHREACT_UNIT *AqHomeReact_FindUnitByUnitId(const AQHOME_REACT *aqh, const char *unitId)
{
  if (aqh && unitId && *unitId) {
    AQHREACT_UNIT *unit;

    unit=AQHREACT_Unit_List_GetById(aqh->unitList, unitId);
    if (unit==NULL) {
      DBG_ERROR(NULL, "Unit \"%s\" not found", unitId);
      return NULL;
    }
    return unit;
  }

  return NULL;
}



void AqHomeReact_AddUnit(AQHOME_REACT *aqh, AQHREACT_UNIT *unit)
{
  if (aqh && unit)
    AQHREACT_Unit_List_Add(unit, aqh->unitList);
}



AQHREACT_UNIT *AqHomeReact_CreateUnitByName(AQHOME_REACT *aqh, const char *unitType)
{
  /* this does not include u_timer and u_varchanges, because those are only created once globally in init.c */
  if (aqh && unitType && *unitType) {
    if (strcasecmp(unitType, "or")==0)
      return AqHomeReact_UnitOr_new(aqh);
    else if (strcasecmp(unitType, "and")==0)
      return AqHomeReact_UnitAnd_new(aqh);
    else if (strcasecmp(unitType, "xor")==0)
      return AqHomeReact_UnitXor_new(aqh);
    else if (strcasecmp(unitType, "valueFilter")==0)
      return AqHomeReact_UnitValueFilter_new(aqh);
    else if (strcasecmp(unitType, "valueSet")==0)
      return AqHomeReact_UnitValueSet_new(aqh);
    else if (strcasecmp(unitType, "stabilize")==0)
      return AqHomeReact_UnitStabilize_new(aqh);
    else if (strcasecmp(unitType, "lowPass")==0)
      return AqHomeReact_UnitLowPass_new(aqh);
    else if (strcasecmp(unitType, "highPass")==0)
      return AqHomeReact_UnitHighPass_new(aqh);
    else if (strcasecmp(unitType, "zeroPosNegString")==0)
      return AqHomeReact_UnitZeroPosNegString_new(aqh);
    else {
      AQHREACT_UNIT *unit;

      DBG_INFO(NULL, "Trying to load network \"%s\"", unitType);
      unit=AQHomeReact_FindAndReadDataDirNetwork(aqh, unitType);
      if (unit==NULL) {
        DBG_ERROR(NULL, "Unknown unit type \"%s\"", unitType);
        return NULL;
      }
      else {
        const char *s;

        s=AQHREACT_Unit_GetTypeName(unit);
        if (!(s && *s && strcasecmp(s, unitType)==0)) {
          DBG_ERROR(NULL, "ERROR: Network file for type \"%s\" contains type \"%s\" instead", unitType, s?s:"<no name>");
          AQHREACT_Unit_free(unit);
          return NULL;
        }
      }
      return unit;
    }
  }

  return NULL;
}











