/****************************************************************************
 * 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 "./param_p.h"
#include "./dataobject.h"

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



GWEN_LIST_FUNCTIONS(AQHREACT_PARAM, AQHREACT_Param)



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

static void _setDbValueFromParamString(const AQHREACT_PARAM *param, GWEN_DB_NODE *db, uint32_t dbFlags);
static void _setDbValueFromParamDouble(const AQHREACT_PARAM *param, GWEN_DB_NODE *db, uint32_t dbFlags);



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

AQHREACT_PARAM *AQHREACT_Param_new()
{
  AQHREACT_PARAM *param;

  GWEN_NEW_OBJECT(AQHREACT_PARAM, param);
  GWEN_LIST_INIT(AQHREACT_PARAM, param);

  return param;
}



void AQHREACT_Param_free(AQHREACT_PARAM *param)
{
  if (param) {
    GWEN_LIST_FINI(AQHREACT_PARAM, param);
    free(param->name);
    free(param->description);
    free(param->stringValue);
    GWEN_FREE_OBJECT(param);
  }
}



const char *AQHREACT_Param_GetName(const AQHREACT_PARAM *param)
{
  return param?param->name:NULL;
}



void AQHREACT_Param_SetName(AQHREACT_PARAM *param, const char *s)
{
  if (param) {
    free(param->name);
    param->name=s?strdup(s):NULL;
  }
}



const char *AQHREACT_Param_GetDescription(const AQHREACT_PARAM *param)
{
  return param?param->description:NULL;
}



void AQHREACT_Param_SetDescription(AQHREACT_PARAM *param, const char *s)
{
  if (param) {
    free(param->description);
    param->description=s?strdup(s):NULL;
  }
}



int AQHREACT_Param_GetDataType(const AQHREACT_PARAM *param)
{
  return param?param->dataType:AQHREACT_DATAOBJECTTYPE_UNKNOWN;
}



void AQHREACT_Param_SetDataType(AQHREACT_PARAM *param, int i)
{
  if (param)
    param->dataType=i;
}



const char *AQHREACT_Param_GetStringValue(const AQHREACT_PARAM *param)
{
  return param?param->stringValue:NULL;
}



void AQHREACT_Param_SetStringValue(AQHREACT_PARAM *param, const char *s)
{
  if (param) {
    free(param->stringValue);
    param->stringValue=s?strdup(s):NULL;
  }
}



double AQHREACT_Param_GetDoubleValue(const AQHREACT_PARAM *param)
{
  return param?param->doubleValue:0.0;
}



void AQHREACT_Param_SetDoubleValue(AQHREACT_PARAM *param, double d)
{
  if (param)
    param->doubleValue=d;
}



uint32_t AQHREACT_Param_GetFlags(const AQHREACT_PARAM *param)
{
  return param?param->flags:0;
}



void AQHREACT_Param_SetFlags(AQHREACT_PARAM *param, uint32_t f)
{
  if (param)
    param->flags=f;
}



void AQHREACT_Param_AddFlags(AQHREACT_PARAM *param, uint32_t f)
{
  if (param)
    param->flags|=f;
}



void AQHREACT_Param_SubFlags(AQHREACT_PARAM *param, uint32_t f)
{
  if (param)
    param->flags&=~f;
}



AQHREACT_PARAM *AQHREACT_Param_List_GetParamByName(const AQHREACT_PARAM_LIST *paramList, const char *paramName)
{
  if (paramList && paramName && *paramName) {
    AQHREACT_PARAM *param;

    param=AQHREACT_Param_List_First(paramList);
    while(param) {
      const char *s;

      s=AQHREACT_Param_GetName(param);
      if (s && *s && strcasecmp(paramName, s)==0)
        return param;
      param=AQHREACT_Param_List_Next(param);
    }
  }
  return NULL;
}



int AQHREACT_Param_List_WriteIntoDb(const AQHREACT_PARAM_LIST *paramList, GWEN_DB_NODE *db, uint32_t dbFlags)
{
  if (paramList && db) {
    const AQHREACT_PARAM *param;

    param=AQHREACT_Param_List_First(paramList);
    while(param) {
      if (param->name) {
	switch(param->dataType) {
	case AQHREACT_DATAOBJECTTYPE_STRING:
	  _setDbValueFromParamString(param, db, dbFlags);
	  break;
	case AQHREACT_DATAOBJECTTYPE_DOUBLE:
	  _setDbValueFromParamDouble(param, db, dbFlags);
	  break;
	default:
	  DBG_ERROR(NULL, "Unhandled param type %d", param->dataType);
	  return GWEN_ERROR_GENERIC;
	}
      }

      param=AQHREACT_Param_List_Next(param);
    }
  }
  return 0;
}



void _setDbValueFromParamString(const AQHREACT_PARAM *param, GWEN_DB_NODE *db, uint32_t dbFlags)
{
  if (param->stringValue)
    GWEN_DB_SetCharValue(db, dbFlags, param->name, param->stringValue);
  else
    GWEN_DB_DeleteVar(db, param->name);
}



void _setDbValueFromParamDouble(const AQHREACT_PARAM *param, GWEN_DB_NODE *db, uint32_t dbFlags)
{
  GWEN_BUFFER *buf;
  int rv;

  buf=GWEN_Buffer_new(0, 32, 0, 1);
  rv=GWEN_Text_DoubleToBuffer(param->doubleValue, buf);
  if (rv<0) {
    DBG_INFO(NULL, "here (%d)", rv);
  }
  else
    GWEN_DB_SetCharValue(db, dbFlags, param->name, GWEN_Buffer_GetStart(buf));
  GWEN_Buffer_free(buf);
}



void AQHREACT_Param_Dump(const AQHREACT_PARAM *param, GWEN_BUFFER *buf, int indent)
{
  if (param && buf) {
    if (indent)
      GWEN_Buffer_FillWithBytes(buf, ' ', indent);

    switch(param->dataType) {
    case AQHREACT_DATAOBJECTTYPE_DOUBLE:
      GWEN_Buffer_AppendArgs(buf, "- %s = %f [DOUBLE]\n", (param->name)?(param->name):"<unnamed>", param->doubleValue);
      break;
    case AQHREACT_DATAOBJECTTYPE_STRING:
      GWEN_Buffer_AppendArgs(buf, "- %s = %s [STRING]\n", (param->name)?(param->name):"<unnamed>", param->stringValue);
      break;
    default:
      DBG_ERROR(NULL, "Unhandled data type %d", param->dataType);
    }
  }
}



void AQHREACT_Param_List_Dump(const AQHREACT_PARAM_LIST *paramList, GWEN_BUFFER *buf, int indent, const char *title)
{
  if (paramList && buf) {
    const AQHREACT_PARAM *param;

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

    param=AQHREACT_Param_List_First(paramList);
    while(param) {
      AQHREACT_Param_Dump(param, buf, indent+2);
      param=AQHREACT_Param_List_Next(param);
    }
  }
}




