/****************************************************************************
 * This file is part of the project AqHome.
 * AqHome (c) by 2025 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 "./mdevices_value.h"

#include "aqhome-cgi/modules/mdataclient.h"

#include <aqcgi/service/module.h>

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


/* ------------------------------------------------------------------------------------------------
 * defs and enums
 * ------------------------------------------------------------------------------------------------
 */

#define GBAS GWEN_Buffer_AppendString
#define GBAA GWEN_Buffer_AppendArgs



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

static void _runValueWithArgs(AQCGI_MODULE *m,
                              AQCGI_REQUEST *rq,
                              AQCGI_SESSION *session,
                              AQH_DATACLIENT *dc,
                              const char *sDeviceName,
                              const char *sValueName,
                              GWEN_BUFFER *dbuf);
static void _writeIntToForm(const char *sValueName, int v, GWEN_BUFFER *dbuf);
static void _mkValueForm(AQH_DATACLIENT *dc, const char *sDeviceName, const AQH_VALUE *value, GWEN_BUFFER *dbuf);
static void _writeRgbwToForm(const char *sValueName, uint32_t color, GWEN_BUFFER *dbuf);
static void _writeOnOffToForm(const char *sValueName, int intVal, GWEN_BUFFER *dbuf);
static void _writeOnOffAutoToForm(const char *sValueName, int intVal, GWEN_BUFFER *dbuf);



/* ------------------------------------------------------------------------------------------------
 * code
 * ------------------------------------------------------------------------------------------------
 */

void AQH_ModDevices_RunValue(AQCGI_MODULE *m, AQCGI_REQUEST *rq, AQCGI_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf)
{
  GWEN_DB_NODE *dbQuery;
  const char *sDeviceName;
  const char *sValueName;

  DBG_ERROR(NULL, "RunValue");
  dbQuery=AQCGI_Request_GetDbQuery(rq);
  sDeviceName=GWEN_DB_GetCharValue(dbQuery, "device", 0, NULL);
  sValueName=GWEN_DB_GetCharValue(dbQuery, "value", 0, NULL);
  if (sDeviceName && *sDeviceName && sValueName && *sValueName) {
    GWEN_BUFFER *bufDeviceName;
    GWEN_BUFFER *bufValueName;

    bufDeviceName=GWEN_Buffer_new(0, 64, 0, 1);
    GWEN_Text_UnescapeToBufferTolerant(sDeviceName, bufDeviceName);
    bufValueName=GWEN_Buffer_new(0, 64, 0, 1);
    GWEN_Text_UnescapeToBufferTolerant(sValueName, bufValueName);
    _runValueWithArgs(m, rq, session, dc,
                      GWEN_Buffer_GetStart(bufDeviceName),
                      GWEN_Buffer_GetStart(bufValueName),
                      dbuf);
    GWEN_Buffer_free(bufValueName);
    GWEN_Buffer_free(bufDeviceName);
  }

#if 0
  if (sDeviceName && *sDeviceName && sValueName && *sValueName) {
    GWEN_BUFFER *pbuf;

    pbuf=GWEN_Buffer_new(0, 256, 0, 1);
    GBAS(pbuf, "Location: /aqbt/devices/value.html?device=");
    GWEN_Text_EscapeToBufferTolerant(sDeviceName, pbuf);
    GBAS(pbuf, "&value=");
    GWEN_Text_EscapeToBufferTolerant(sValueName, pbuf);
    AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(pbuf));
    GWEN_Buffer_free(pbuf);
  }
  AQCGI_Request_SetResponseCode(rq, 303);
  AQCGI_Request_SetResponseText(rq, "See other");
#endif
}



void _runValueWithArgs(AQCGI_MODULE *m,
                       AQCGI_REQUEST *rq,
                       AQCGI_SESSION *session,
                       AQH_DATACLIENT *dc,
                       const char *sDeviceName,
                       const char *sValueName,
                       GWEN_BUFFER *dbuf)
{
  GWEN_DB_NODE *dbQuery;
  AQH_VALUE_LIST *valueList;

  dbQuery=AQCGI_Request_GetDbQuery(rq);
  DBG_ERROR(NULL, "Device=%s, value=%s", sDeviceName?sDeviceName:"<empty>", sValueName?sValueName:"<empty>");

  GBAA(dbuf,"<h1>Value %s/%s</h1>\n", sDeviceName, sValueName);

  valueList=AQH_DataClient_GetValues(dc, sDeviceName, 0);
  if (valueList) {
    const AQH_VALUE *value;

    value=AQH_Value_List_First(valueList);
    while(value) {
      const char *s;

      s=AQH_Value_GetName(value);
      if (s && *s && strcasecmp(s, sValueName)==0)
        break;
      value=AQH_Value_List_Next(value);
    }
    if (value && AQH_Value_GetValueType(value)==AQH_ValueType_Actor) {
      _mkValueForm(dc, sDeviceName, value, dbuf);
    }
    else {
      GBAS(dbuf, "<table>\n");
      GBAS(dbuf, "<tr><td>");
      GBAS(dbuf, "<img src=\"graph.html?device=");
      GWEN_Text_EscapeToBufferTolerant(sDeviceName, dbuf);
      GBAS(dbuf, "&value=");
      GWEN_Text_EscapeToBufferTolerant(sValueName, dbuf);
      GBAS(dbuf, "&period=4h\"/>");
      GBAS(dbuf, "</td></tr>");

      GBAS(dbuf, "<tr><td>");
      GBAS(dbuf, "<img src=\"graph.html?device=");
      GWEN_Text_EscapeToBufferTolerant(sDeviceName, dbuf);
      GBAS(dbuf, "&value=");
      GWEN_Text_EscapeToBufferTolerant(sValueName, dbuf);
      GBAS(dbuf, "&period=1d\"/>");
      GBAS(dbuf, "</td></tr>");

      GBAS(dbuf, "<tr><td>");
      GBAS(dbuf, "<img src=\"graph.html?device=");
      GWEN_Text_EscapeToBufferTolerant(sDeviceName, dbuf);
      GBAS(dbuf, "&value=");
      GWEN_Text_EscapeToBufferTolerant(sValueName, dbuf);
      GBAS(dbuf, "&period=1w\"/>");
      GBAS(dbuf, "</td></tr>");

      GBAS(dbuf, "</table>");
    }
    AQH_Value_List_free(valueList);
  }
}



void _mkValueForm(AQH_DATACLIENT *dc, const char *sDeviceName, const AQH_VALUE *value, GWEN_BUFFER *dbuf)
{
  const char *sValueSystemName;
  const char *sValueName;
  uint64_t dataPoints[2];
  uint64_t recvdNum;
  //  uint64_t timestamp;
  union {double f; uint64_t i;} u;
  int intVal;

  sValueSystemName=AQH_Value_GetNameForSystem(value);
  sValueName=AQH_Value_GetName(value);
  recvdNum=AQH_DataClient_GetLastData(dc, sValueSystemName, &dataPoints[0], 1);
  if (recvdNum>0) {
    //    timestamp=dataPoints[0];
    u.i=dataPoints[1];
    intVal=(int) u.f;
  }
  else {
    u.i=0;
    intVal=-1;
  }

  GBAS(dbuf,"<form action=\"setdata.html\" method=\"post\">\n");
  GBAA(dbuf, "<input type=\"hidden\" name=\"device\" value=\"%s\">\n", sDeviceName);
  GBAA(dbuf, "<input type=\"hidden\" name=\"value\"  value=\"%s\">\n", sValueName);

  DBG_ERROR(NULL, "Adding actor");
  switch(AQH_Value_GetModality(value)) {
  case AQH_ValueModality_RGBW:      _writeRgbwToForm(sValueName, u.f, dbuf);         break;
  case AQH_ValueModality_OnOff:     _writeOnOffToForm(sValueName, intVal, dbuf);     break;
  case AQH_ValueModality_OnOffAuto: _writeOnOffAutoToForm(sValueName, intVal, dbuf); break;
  default:                          _writeIntToForm(sValueName, intVal, dbuf);       break;
  } /* switch */

  GBAS(dbuf,"<input type=\"submit\" name=\"action\" value=\"Send\"/>");
  GBAS(dbuf, "</form>\n\n");
}



void _writeIntToForm(const char *sValueName, int v, GWEN_BUFFER *dbuf)
{
  GBAA(dbuf, "<input type=\"number\" name=\"%s\" value=\"%d\"/>", sValueName, v);
}



void _writeRgbwToForm(const char *sValueName, uint32_t color, GWEN_BUFFER *dbuf)
{
#if 1
  GBAA(dbuf, "<input type=\"text\" name=\"%s\" value=\"#%08x\"/>", sValueName, color);
#else
  GBAA(dbuf, "<input type=\"color\" name=\"%s\" value=\"#%08x\"/>#%08x (#%08x)",
       sValueName,
       AQH_ModDevices_RgbwToHtmlColor(color),
       AQH_ModDevices_RgbwToHtmlColor(color),
       color);
#endif
}



void _writeOnOffToForm(const char *sValueName, int intVal, GWEN_BUFFER *dbuf)
{
  GBAA(dbuf, "<select name=\"%s\">" "<option value=\"unchanged\" >unchanged</option>", sValueName);
  GBAA(dbuf, "<option value=\"off\" %s>off</option>", (intVal==0)?"selected":"");
  GBAA(dbuf, "<option value=\"on\" %s>on</option>", (intVal==1)?"selected":"");
  GBAS(dbuf, "</select>");
}



void _writeOnOffAutoToForm(const char *sValueName, int intVal, GWEN_BUFFER *dbuf)
{
  GBAA(dbuf, "<select name=\"%s\">" "<option value=\"unchanged\" >unchanged</option>", sValueName);
  GBAA(dbuf, "<option value=\"off\" %s>off</option>", (intVal==0)?"selected":"");
  GBAA(dbuf, "<option value=\"on\" %s>on</option>", (intVal==1)?"selected":"");
  GBAA(dbuf, "<option value=\"auto\" %s>auto</option>", (intVal==2)?"selected":"");
  GBAS(dbuf, "</select>");
}



