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


/* This file is included by "prgrule.c" */


#include <gwenhywfar/testframework.h>
#include "prgrule-t.h"


#ifdef AQHOME_ENABLE_TESTCODE


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

static int GWENHYWFAR_CB test1(GWEN_TEST_MODULE *mod);
static int GWENHYWFAR_CB test2(GWEN_TEST_MODULE *mod);
static int GWENHYWFAR_CB test3(GWEN_TEST_MODULE *mod);

static int testAgainstValues(const char *ruleText, const uint64_t *ptrExpectedFields, double expectedValue);



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


int AQHREACT_PrgRule_AddTests(GWEN_TEST_MODULE *mod)
{
  GWEN_TEST_MODULE *newMod;

  newMod=GWEN_Test_Module_AddModule(mod, "AQHREACT_PrgRule", NULL);

  GWEN_Test_Module_AddTest(newMod, "parse rules 1", test1, NULL);
  GWEN_Test_Module_AddTest(newMod, "parse rules 2", test2, NULL);
  GWEN_Test_Module_AddTest(newMod, "match rules 1", test3, NULL);

  return 0;
}



int test1(GWEN_UNUSED GWEN_TEST_MODULE *mod)
{
  static char ruleText[]="* * * * * 10.0";
  uint64_t expectedFields[]={
    0b111111111111111111111111111111111111111111111111111111111111L, /* minute */
                                        0b111111111111111111111111L, /* hour */
                                0b11111111111111111111111111111110L, /* day of month */
                                                   0b1111111111110L, /* month */
                                                         0b1111111L  /* day of week (0=sunday) */
  };

  return testAgainstValues(ruleText, expectedFields, 10.0);
}



int test2(GWEN_UNUSED GWEN_TEST_MODULE *mod)
{
  static char ruleText[]="/2 4-7 1-5,8,15,23-25 * 0,3,5 12.3";
  uint64_t expectedFields[]={
    0b010101010101010101010101010101010101010101010101010101010101L, /* minute */
                                        0b000000000000000011110000L, /* hour */
                                0b00000011100000001000000100111110L, /* day of month */
                                                   0b1111111111110L, /* month */
                                                         0b0101001L  /* day of week (0=sunday) */
  };

  return testAgainstValues(ruleText, expectedFields, 12.3);
}



int test3(GWEN_UNUSED GWEN_TEST_MODULE *mod)
{
  AQHREACT_PRGRULE_LIST *prgRuleList;
  AQHREACT_PRGRULE *prgRule;
  static char ruleText[]="/2 4-7 1-5,8,15,23-25 * 0,1,3,5 12.3";

  prgRuleList=AQHREACT_PrgRule_ReadRules(ruleText);
  if (prgRuleList==NULL) {
    DBG_ERROR(NULL, "Error reading rules list");
    return GWEN_ERROR_GENERIC;
  }

  prgRule=AQHREACT_PrgRule_List_First(prgRuleList);

  if (!AQHREACT_PrgRule_Matches(prgRule, 2, 5, 8, 4, 1)) {
    DBG_ERROR(NULL, "Error matching against rule");
    return GWEN_ERROR_GENERIC;
  }

  return 0;
}




int testAgainstValues(const char *ruleText, const uint64_t *ptrExpectedFields, double expectedValue)
{
  AQHREACT_PRGRULE_LIST *prgRuleList;
  AQHREACT_PRGRULE *prgRule;

  prgRuleList=AQHREACT_PrgRule_ReadRules(ruleText);
  if (prgRuleList==NULL) {
    DBG_ERROR(NULL, "Error reading rules list");
    return GWEN_ERROR_GENERIC;
  }

  prgRule=AQHREACT_PrgRule_List_First(prgRuleList);
  if (AQHREACT_PrgRule_List_Next(prgRule)) {
    DBG_ERROR(NULL, "More than one rule read when only one given");
    return GWEN_ERROR_GENERIC;
  }

  if (prgRule->bitfieldMinute!=ptrExpectedFields[0]) {
    DBG_ERROR(NULL, "Unexpected value for MINUTE: %016lX [%016lX]", prgRule->bitfieldMinute, ptrExpectedFields[0]);
    AQHREACT_PrgRule_List_free(prgRuleList);
    return GWEN_ERROR_GENERIC;
  }

  if (prgRule->bitfieldHour!=ptrExpectedFields[1]) {
    DBG_ERROR(NULL, "Unexpected value for HOUR: %016X  [%016lX]", prgRule->bitfieldHour, ptrExpectedFields[1]);
    AQHREACT_PrgRule_List_free(prgRuleList);
    return GWEN_ERROR_GENERIC;
  }

  if (prgRule->bitfieldDayOfMonth!=ptrExpectedFields[2]) {
    DBG_ERROR(NULL, "Unexpected value for DAYOFMONTH: %016X [%016lX]", prgRule->bitfieldDayOfMonth, ptrExpectedFields[2]);
    AQHREACT_PrgRule_List_free(prgRuleList);
    return GWEN_ERROR_GENERIC;
  }

  if (prgRule->bitfieldMonth!=ptrExpectedFields[3]) {
    DBG_ERROR(NULL, "Unexpected value for MONTH: %016X [%016lX]", prgRule->bitfieldMonth, ptrExpectedFields[3]);
    AQHREACT_PrgRule_List_free(prgRuleList);
    return GWEN_ERROR_GENERIC;
  }

  if (prgRule->bitfieldDayOfWeek!=ptrExpectedFields[4]) {
    DBG_ERROR(NULL, "Unexpected value for DAYOFWEEK: %08X [%016lX]", prgRule->bitfieldDayOfWeek, ptrExpectedFields[4]);
    AQHREACT_PrgRule_List_free(prgRuleList);
    return GWEN_ERROR_GENERIC;
  }

  if (prgRule->value!=expectedValue) {
    DBG_ERROR(NULL, "Unexpected value : %f", prgRule->value);
    AQHREACT_PrgRule_List_free(prgRuleList);
    return GWEN_ERROR_GENERIC;
  }

  return 0;
}




#else

int AQHREACT_PrgRule_AddTests(GWEN_TEST_MODULE *mod)
{
  DBG_ERROR(GWEN_LOGDOMAIN, "AqHome was compiled without test code enabled.");
  return GWEN_ERROR_GENERIC;
}


#endif



