/****************************************************************************
 * 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.
 ****************************************************************************/

#ifndef AQHOME_REACT_UNIT_H
#define AQHOME_REACT_UNIT_H


#include <gwenhywfar/list.h>
#include <gwenhywfar/inherit.h>


typedef struct AQHREACT_UNIT AQHREACT_UNIT;
GWEN_LIST_FUNCTION_DEFS(AQHREACT_UNIT, AQHREACT_Unit)
GWEN_INHERIT_FUNCTION_DEFS(AQHREACT_UNIT)


#define AQHREACT_UNIT_FLAGS_CHANGED 0x80000000
#define AQHREACT_UNIT_FLAGS_INUSE   0x40000000
#define AQHREACT_UNIT_FLAGS_MULTI   0x20000000
#define AQHREACT_UNIT_FLAGS_INVERT  0x10000000 /** invert output of boolean units */


#include "aqhome-react/server.h"
#include "aqhome-react/types/port.h"
#include "aqhome-react/types/param.h"
#include "aqhome-react/types/dataobject.h"


typedef void (*AQHREACT_UNIT_INPUTDATA_FN)(AQHREACT_UNIT *unit, AQHREACT_PORT *port, const AQHREACT_DATAOBJECT *dataObject);
typedef void (*AQHREACT_UNIT_OUTPUTDATA_FN)(AQHREACT_UNIT *unit, AQHREACT_PORT *port, const AQHREACT_DATAOBJECT *dataObject);
typedef AQHREACT_PARAM* (*AQHREACT_UNIT_GETPARAMBYNAME_FN)(const AQHREACT_UNIT *unit, const char *paramName);
typedef int (*AQHREACT_UNIT_PROCESS_FN)(AQHREACT_UNIT *unit);
typedef void (*AQHREACT_UNIT_DUMP_FN)(const AQHREACT_UNIT *unit, GWEN_BUFFER *buf, int indent);




AQHREACT_UNIT *AQHREACT_Unit_new(AQH_OBJECT *aqh);
void AQHREACT_Unit_free(AQHREACT_UNIT *unit);

AQH_OBJECT *AQHREACT_Unit_GetAqHomeReact(const AQHREACT_UNIT *unit);

const char *AQHREACT_Unit_GetTypeName(const AQHREACT_UNIT *unit);
void AQHREACT_Unit_SetTypeName(AQHREACT_UNIT *unit, const char *s);

const char *AQHREACT_Unit_GetDescription(const AQHREACT_UNIT *unit);
void AQHREACT_Unit_SetDescription(AQHREACT_UNIT *unit, const char *s);

const char *AQHREACT_Unit_GetId(const AQHREACT_UNIT *unit);
void AQHREACT_Unit_SetId(AQHREACT_UNIT *unit, const char *s);

uint32_t AQHREACT_Unit_GetFlags(const AQHREACT_UNIT *unit);
void AQHREACT_Unit_SetFlags(AQHREACT_UNIT *unit, uint32_t i);
void AQHREACT_Unit_AddFlags(AQHREACT_UNIT *unit, uint32_t i);
void AQHREACT_Unit_SubFlags(AQHREACT_UNIT *unit, uint32_t i);

/** general purpose timestamp, unit is free to use it */
uint64_t AQHREACT_Unit_GetGpTimestamp(const AQHREACT_UNIT *unit);
void AQHREACT_Unit_SetGpTimestamp(AQHREACT_UNIT *unit, uint64_t t);

/** general purpose integer, unit is free to use it */
int AQHREACT_Unit_GetGpInt(const AQHREACT_UNIT *unit);
void AQHREACT_Unit_SetGpInt(AQHREACT_UNIT *unit, int i);


AQHREACT_PORT_LIST *AQHREACT_Unit_GetInputPortList(const AQHREACT_UNIT *unit);
void AQHREACT_Unit_AddInputPort(AQHREACT_UNIT *unit, AQHREACT_PORT *port);
AQHREACT_PORT *AQHREACT_Unit_GetInputPortByName(const AQHREACT_UNIT *unit, const char *s);
AQHREACT_PORT *AQHREACT_Unit_GetInputPortByIdForUnit(const AQHREACT_UNIT *unit, int id);
AQHREACT_PORT *AQHREACT_Unit_GetOrCreateUnusedInputPortByName(AQHREACT_UNIT *unit, const char *s);

AQHREACT_PORT_LIST *AQHREACT_Unit_GetOutputPortList(const AQHREACT_UNIT *unit);
void AQHREACT_Unit_AddOutputPort(AQHREACT_UNIT *unit, AQHREACT_PORT *port);
AQHREACT_PORT *AQHREACT_Unit_GetOutputPortByName(const AQHREACT_UNIT *unit, const char *s);
AQHREACT_PORT *AQHREACT_Unit_GetOutputPortByIdForUnit(const AQHREACT_UNIT *unit, int id);

void AQHREACT_Unit_SetNextInputPortId(AQHREACT_UNIT *unit, int i);

void AQHREACT_Unit_ClearChangeFlagsInUnitAndInputPorts(AQHREACT_UNIT *unit);
int AQHREACT_Unit_InputHasChanged(const AQHREACT_UNIT *unit);


AQHREACT_PARAM_LIST *AQHREACT_Unit_GetParamList(const AQHREACT_UNIT *unit);
void AQHREACT_Unit_AddParam(AQHREACT_UNIT *unit, AQHREACT_PARAM *param);
AQHREACT_PARAM *AQHREACT_Unit_GetParamByName(const AQHREACT_UNIT *unit, const char *s);
double AQHREACT_Unit_GetParamValueDouble(const AQHREACT_UNIT *unit, const char *s, double defVal);
void AQHREACT_Unit_SetParamValueDouble(AQHREACT_UNIT *unit, const char *paramName, double val);
const char *AQHREACT_Unit_GetParamValueString(const AQHREACT_UNIT *unit, const char *paramName, const char *defVal);
void AQHREACT_Unit_SetParamValueString(AQHREACT_UNIT *unit, const char *paramName, const char *val);

void AQHREACT_Unit_OutputData(AQHREACT_UNIT *unit, AQHREACT_PORT *port, const AQHREACT_DATAOBJECT *dataObject);
void AQHREACT_Unit_OutputDoubleData(AQHREACT_UNIT *unit, AQHREACT_PORT *port, double data);
void AQHREACT_Unit_OutputStringData(AQHREACT_UNIT *unit, AQHREACT_PORT *port, const char *data);


void AQHREACT_Unit_InputData(AQHREACT_UNIT *unit, AQHREACT_PORT *port, const AQHREACT_DATAOBJECT *dataObject);

/**
 * Process inputs and generate output.
 *
 * @return >0 if something done, 0 if nothing done (response of internal implementation), <0 on error
 * @param unit unit object
 */
int AQHREACT_Unit_Process(AQHREACT_UNIT *unit);


AQHREACT_UNIT_INPUTDATA_FN AQHREACT_Unit_SetInputDataFn(AQHREACT_UNIT *unit, AQHREACT_UNIT_INPUTDATA_FN f);
AQHREACT_UNIT_OUTPUTDATA_FN AQHREACT_Unit_SetOutputDataFn(AQHREACT_UNIT *unit, AQHREACT_UNIT_OUTPUTDATA_FN f);
AQHREACT_UNIT_GETPARAMBYNAME_FN AQHREACT_Unit_SetGetParamByNameFn(AQHREACT_UNIT *unit, AQHREACT_UNIT_GETPARAMBYNAME_FN f);
AQHREACT_UNIT_PROCESS_FN AQHREACT_Unit_SetProcessFn(AQHREACT_UNIT *unit, AQHREACT_UNIT_PROCESS_FN f);
AQHREACT_UNIT_DUMP_FN AQHREACT_Unit_SetDumpFn(AQHREACT_UNIT *unit, AQHREACT_UNIT_DUMP_FN f);


AQHREACT_UNIT *AQHREACT_Unit_List_GetById(const AQHREACT_UNIT_LIST *unitList, const char *id);

void AQHREACT_Unit_Dump(const AQHREACT_UNIT *unit, GWEN_BUFFER *buf, int indent);
void AQHREACT_Unit_List_Dump(const AQHREACT_UNIT_LIST *unitList, GWEN_BUFFER *buf, int indent, const char *title);


#endif

