/****************************************************************************
 * 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 "./c_setdata.h"
#include "aqhome/data/value.h"
#include "aqhome/ipc/data/msg_data_set.h"
#include "aqhome/mqtt/msg_mqtt_publish.h"

#include <gwenhywfar/debug.h>



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

static void _sendDataForDevice(AQHOME_MQTT *aqh, const AQHMQTT_DEVICE *device, const char *valueName, const char *valueData);
static void _sendValueToMqtt(AQHOME_MQTT *aqh, const char *deviceId, const AQHMQTT_TOPIC *topic, const char *valueData);
static GWEN_BUFFER *_createBufferForTopic(const char *deviceId, const AQHMQTT_TOPIC *topic);



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

void AqHomeMqttLog_HandleSetData(AQHOME_MQTT *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *recvdMsg)
{
  AQH_VALUE *recvdValue;

  DBG_ERROR(NULL, "Received SETDATA request");
  AQH_SetDataIpcMsg_Parse(recvdMsg, 0);
  recvdValue=AQH_SetDataIpcMsg_ReadValue(recvdMsg);
  if (recvdValue) {
    const char *valueName;
    const char *deviceName;

    valueName=recvdValue?AQH_Value_GetName(recvdValue):NULL;
    deviceName=recvdValue?AQH_Value_GetDeviceName(recvdValue):NULL;
    if (valueName && deviceName) {
      AQHMQTT_DEVICE *device;

      device=AqHomeMqtt_FindRegisteredDevice(aqh, deviceName);
      if (device) {
        char *valueDataFreeable;

        DBG_ERROR(NULL, "Sending data to value \"%s\" of device \"%s\"", valueName, deviceName);
        valueDataFreeable=AQH_SetDataIpcMsg_ReadData(recvdMsg);
        _sendDataForDevice(aqh, device, valueName, valueDataFreeable);
        free(valueDataFreeable);
      }
      else {
        DBG_ERROR(NULL, "Device \"%s\" not found", deviceName);
        AqHomeMqtt_DumpRegisteredDevices(aqh);
      }
    }
    else {
      DBG_ERROR(NULL, "Either value name or device name missing in request");
    }
    AQH_Value_free(recvdValue);
  }
  else {
    DBG_ERROR(NULL, "Request does not contain a value object");
  }
}



void _sendDataForDevice(AQHOME_MQTT *aqh, const AQHMQTT_DEVICE *device, const char *valueName, const char *valueData)
{
  const char *deviceId;

  deviceId=AQHMQTT_Device_GetId(device);
  if (deviceId && *deviceId) {
    AQHMQTT_TOPIC_LIST *topicList;

    topicList=AQHMQTT_Device_GetTopicList(device);
    if (topicList) {
      AQHMQTT_TOPIC *topic;

      topic=AQHMQTT_Topic_List_First(topicList);
      while(topic) {
        if (AQHMQTT_Topic_GetDirection(topic)==AQHMQTT_TopicDir_Out) {
          AQHMQTT_VALUE_LIST *valueList;
          AQHMQTT_VALUE *value;

          valueList=AQHMQTT_Topic_GetValueList(topic);
          value=valueList?AQHMQTT_Value_List_GetByName(valueList, valueName):NULL;
          if (value) {
            /* found value, create publish msg, send */
            DBG_ERROR(NULL, "Topic \"%s\" contains value \"%s\"", AQHMQTT_Topic_GetName(topic), valueName);
            _sendValueToMqtt(aqh, deviceId, topic, valueData);
          }
        } /* if out */
        topic=AQHMQTT_Topic_List_Next(topic);
      } /* while topic */
    }
  }
  else {
    DBG_ERROR(NULL, "Device has no id");
  }
}



void _sendValueToMqtt(AQHOME_MQTT *aqh, const char *deviceId, const AQHMQTT_TOPIC *topic, const char *valueData)
{
  GWEN_MSG_ENDPOINT *ep;
  GWEN_BUFFER *buf;
  GWEN_MSG *msgOut;

  ep=AqHomeMqtt_GetMqttEndpoint(aqh);
  buf=_createBufferForTopic(deviceId, topic);
  DBG_ERROR(NULL, "MQTT PUBLISH: %s = %s", GWEN_Buffer_GetStart(buf), valueData?valueData:"<empty>");
  msgOut=AQH_PublishMqttMsg_new(0, 0, GWEN_Buffer_GetStart(buf),
                                (const uint8_t*) (valueData?valueData:NULL),
                                valueData?strlen(valueData):0);
  if (msgOut) {
    GWEN_MsgEndpoint_AddSendMessage(ep, msgOut);
  }
  else {
    DBG_ERROR(NULL, "Error creating message");
  }
  GWEN_Buffer_free(buf);
}



GWEN_BUFFER *_createBufferForTopic(const char *deviceId, const AQHMQTT_TOPIC *topic)
{
  GWEN_BUFFER *buf;
  const char *s;

  buf=GWEN_Buffer_new(0, 256, 0, 1);
  s=AQHMQTT_Topic_GetBeforeId(topic);
  if (s && *s)
    GWEN_Buffer_AppendString(buf, s);
  GWEN_Buffer_AppendString(buf, deviceId);
  s=AQHMQTT_Topic_GetAfterId(topic);
  if (s && *s)
    GWEN_Buffer_AppendString(buf, s);
  return buf;
}






