
#ifndef CONFIG_H_
#define CONFIG_H_

#include "utils.h"
#include "aq_serial.h"
#include "aqualink.h"

//#define DEFAULT_LOG_LEVEL    10 
#define DEFAULT_LOG_LEVEL    LOG_NOTICE
//#define DEFAULT_WEBPORT      "6580"
//#define DEFAULT_WEBROOT      "./"
#define DEFAULT_WEBPORT      "80"
#define DEFAULT_WEBROOT      "/var/www/aqualinkd/"
#define DEFAULT_SERIALPORT   "/dev/ttyUSB0"
#define DEFAULT_DEVICE_ID    "0x0a"
//#define DEFAULT_MQTT_DZ_IN   NULL // "domoticz/in"
//#define DEFAULT_MQTT_DZ_OUT  NULL // "domoticz/out"
#define DEFAULT_DISCOVERY    "homeassistant"
#define DEFAULT_MQTT_AQ_TP   "aqualinkd"
#define DEFAULT_MQTT_SERVER  NULL
#define DEFAULT_MQTT_USER    NULL
#define DEFAULT_MQTT_PASSWD  NULL

//#define DEFAULT_SWG_ZERO_IGNORE_COUNT 0

#define MQTT_ID_LEN 18 // 20 seems to kill mosquitto 1.6

// For aqconfig.read_RS485_devmask
#define READ_RS485_SWG           (1 << 0) // 1   SWG
#define READ_RS485_JAN_PUMP      (1 << 1) // 2   Jandy Pump
#define READ_RS485_PEN_PUMP      (1 << 2) // 4   Pentair Pump
#define READ_RS485_JAN_JXI       (1 << 3) //    Jandy JX & LXi heater
#define READ_RS485_JAN_LX        (1 << 4) //     Jandy LX heater
#define READ_RS485_JAN_CHEM_FEDR (1 << 5) //     Jandy Chemical Feeder - rename to READ_RS485_JAN_CHEM_FEDR
#define READ_RS485_IAQUALNK      (1 << 6) // Read iAqualink messages 
#define READ_RS485_HEATPUMP      (1 << 7) // Read HeatPump messages
#define READ_RS485_JLIGHT        (1 << 8) // Read Jandy infinite watercolor light
#define READ_RS485_JAN_CHEM_ANLZ (1 << 9) // Read TrueSens

#define MAX_RSSD_LOG_FILTERS 4

struct aqconfig
{
  char *config_file;
  char *listen_address;
  char *serial_port;
  unsigned int log_level;
  unsigned int mg_log_level;
  char *web_directory;
  unsigned char device_id;
  unsigned char rssa_device_id;
  uint16_t paneltype_mask;
  unsigned char extended_device_id;
  unsigned char extended_device_id2;
  bool extended_device_id_programming;
  bool enable_iaqualink;
  //bool enable_RS_device_value_print;
  bool deamonize;
#ifndef AQ_MANAGER // Need to uncomment and clean up referances in future.
  char *log_file;
#endif
  char *mqtt_aq_topic;
  //char *mqtt_hass_discover_topic;
  char *mqtt_discovery_topic;
  char *mqtt_server;
  char *mqtt_user;
  char *mqtt_passwd;
  //bool mqtt_hass_discover_use_mac;
  bool mqtt_discovery_use_mac;
  //char mqtt_ID[MQTT_ID_LEN+1];
  float light_programming_mode;
  int light_programming_initial_on;
  int light_programming_initial_off;
  bool light_programming_advance_mode;
  bool override_freeze_protect;
#ifdef AQ_PDA
  bool pda_sleep_mode;
#endif
  bool convert_mqtt_temp;
 
  bool report_zero_spa_temp;
  bool report_zero_pool_temp;
  //bool read_all_devices;
  //bool read_pentair_packets;
  uint16_t read_RS485_devmask;
  bool use_panel_aux_labels; // Took this option out of config

  uint8_t force_device_devmask;

  //int swg_zero_ignore; // This can be removed since this was due to VSP that's been fixed.
  bool display_warnings_web;
  bool log_protocol_packets; // Read & Write as packets
  bool log_raw_bytes; // Read as bytes
  unsigned char RSSD_LOG_filter[MAX_RSSD_LOG_FILTERS];
  //bool log_raw_RS_bytes;

  bool mqtt_timed_update;
  bool sync_panel_time;
  bool enable_scheduler;
  int8_t schedule_event_mask; // Was int16_t, but no need
  int  sched_chk_pumpon_hour;
  int  sched_chk_pumpoff_hour;
  char *sched_chk_booston_device;
  bool ftdi_low_latency;
  int frame_delay;
  bool device_pre_state;
  bool save_debug_log_masks;
  bool save_light_programming_value;
  int sensor_poll_time;
};

#ifndef CONFIG_C
extern struct aqconfig _aqconfig_;
#else
struct aqconfig _aqconfig_;
#endif


#define READ_RSDEV_SWG ((_aqconfig_.read_RS485_devmask & READ_RS485_SWG) == READ_RS485_SWG)
#define READ_RSDEV_ePUMP ((_aqconfig_.read_RS485_devmask & READ_RS485_JAN_PUMP) == READ_RS485_JAN_PUMP)
#define READ_RSDEV_vsfPUMP ((_aqconfig_.read_RS485_devmask & READ_RS485_PEN_PUMP) == READ_RS485_PEN_PUMP)
#define READ_RSDEV_JXI ((_aqconfig_.read_RS485_devmask & READ_RS485_JAN_JXI) == READ_RS485_JAN_JXI)
#define READ_RSDEV_LX ((_aqconfig_.read_RS485_devmask & READ_RS485_JAN_LX) == READ_RS485_JAN_LX)
#define READ_RSDEV_CHEM_FEDR ((_aqconfig_.read_RS485_devmask & READ_RS485_JAN_CHEM_FEDR) == READ_RS485_JAN_CHEM_FEDR)
#define READ_RSDEV_CHEM_ANLZ ((_aqconfig_.read_RS485_devmask & READ_RS485_JAN_CHEM_ANLZ) == READ_RS485_JAN_CHEM_ANLZ)
#define READ_RSDEV_iAQLNK ((_aqconfig_.read_RS485_devmask & READ_RS485_IAQUALNK) == READ_RS485_IAQUALNK)
#define READ_RSDEV_HPUMP ((_aqconfig_.read_RS485_devmask & READ_RS485_HEATPUMP) == READ_RS485_HEATPUMP)
#define READ_RSDEV_JLIGHT ((_aqconfig_.read_RS485_devmask & READ_RS485_JLIGHT) == READ_RS485_JLIGHT)

#define isPDA_IAQT (_aqconfig_.device_id == 0x33)
//#define isPDA ((_aqconfig_.paneltype_mask & RSP_PDA) == RSP_PDA)


#define FORCE_SWG_SP           (1 << 0)
#define FORCE_POOLSPA_SP       (1 << 1)
#define FORCE_FREEZEPROTECT_SP (1 << 2)
#define FORCE_CHEM_FEEDER      (1 << 3) // rename to FORCE_CHEMICALS
#define FORCE_CHILLER          (1 << 4)

#define ENABLE_SWG           ((_aqconfig_.force_device_devmask & FORCE_SWG_SP) == FORCE_SWG_SP)
#define ENABLE_HEATERS       ((_aqconfig_.force_device_devmask & FORCE_POOLSPA_SP) == FORCE_POOLSPA_SP)
#define ENABLE_FREEZEPROTECT ((_aqconfig_.force_device_devmask & FORCE_FREEZEPROTECT_SP) == FORCE_FREEZEPROTECT_SP)
#define ENABLE_CHEM_FEEDER   ((_aqconfig_.force_device_devmask & FORCE_CHEM_FEEDER) == FORCE_CHEM_FEEDER)
#define ENABLE_CHILLER       ((_aqconfig_.force_device_devmask & FORCE_CHILLER) == FORCE_CHILLER)

/*
#ifndef CONFIG_C
#ifdef AQUALINKD_C
extern struct aqconfig _aqconfig_;
#else
extern const struct aqconfig _aqconfig_;
#endif
#endif
*/

void init_parameters (struct aqconfig * parms);
//bool parse_config (struct aqconfig * parms, char *cfgfile);
//void readCfg (struct aqconfig *config_parameters, char *cfgFile);
//void readCfg (struct aqconfig *config_parameters, struct aqualinkdata *aqualink_data, char *cfgFile);
void read_config(struct aqualinkdata *aqdata, char *cfgFile);
void init_config();

bool writeCfg (struct aqualinkdata *aqdata);
bool setConfigValue(struct aqualinkdata *aqdata, char *param, char *value);
//bool mac(char *buf, int len, bool useDelimiter);
char *cleanalloc(char *str);
char *ncleanalloc(char *str, int length);



const char *pumpType2String(pump_type ptype);

int save_config_js(const char* inBuf, int inSize, char* outBuf, int outSize, struct aqualinkdata *aqdata);
void check_print_config (struct aqualinkdata *aqdata);


typedef enum cfg_value_type{
  CFG_STRING,
  CFG_INT,
  CFG_FLOAT,
  CFG_HEX,
  CFG_BOOL,
  CFG_BITMASK,
  CFG_SPECIAL
} cfg_value_type;


#define CFG_PERSISTANT        (1 << 0) // Don't free memory, things referance the pointer
#define CFG_GRP_ADVANCED      (1 << 1) // Show in group advanced
#define CFG_READONLY          (1 << 2) // Don't show in UI, but do write to CFG file. (Maybe display in UI but no edit)
#define CFG_HIDE              (1 << 3) // Don't show in any UI listing, don't write to CFG file.
//#define CFG_READONLY          (1 << 4) // Don't show in UI, but do write to CFG file.
#define CFG_PASSWD_MASK       (1 << 4) // Mask password with *****
#define CFG_FORCE_RESTART     (1 << 5) // Force aqualinkd to restart
#define CFG_ALLOW_BLANK       (1 << 6) // Allow blank entry
#define CFG_GREYED_OUT        (1 << 7) // Greyout in UI, show but not editable
//#define CFG_      (1 << 3)

// Text to show when CFG_PASSWD_MASK is set
#define PASSWD_MASK_TEXT "********"

#define isMASKSET(mask, bit) ((mask & bit) == bit)

typedef struct cfgParam {
  void *value_ptr;
  void *default_value;
  cfg_value_type value_type;
  uint16_t config_mask;
  char *name;
  char *valid_values;
  uint16_t mask;
  //bool advanced;
} cfgParam;

#ifndef CONFIG_C
extern cfgParam _cfgParams[];
extern int _numCfgParams;
#else
cfgParam _cfgParams[100];
int _numCfgParams;
#endif // CONFIG_C


// Below are missed
//RSSD_LOG_filter
//debug_log_mask

#define CFG_V_BOOL                              "[\"Yes\", \"No\"]"

#define CFG_N_serial_port                       "serial_port"
#define CFG_N_log_level                         "log_level"
#define CFG_N_MG_log_level                      "mg_log_level"
#define CFG_V_log_level                         "[\"DEBUG_SERIAL\", \"DEBUG\", \"INFO\", \"NOTICE\", \"WARNING\", \"ERROR\"]"
#define CFG_N_listen_address                    "listen_address" 
#define CFG_N_web_directory                     "web_directory"
#define CFG_N_device_id                         "device_id"

#define CFG_V_device_id                         "[\"0x0a\", \"0x0b\", \"0x09\", \"0x08\", \"0x60\", \"0x33\", \"0xFF\"]"
#define CFG_V_device_id_RS                      "[\"0x0a\", \"0x0b\", \"0x09\", \"0x08\", \"0xFF\"]"
#define CFG_V_device_id_PDA                     "[\"0x60\", \"0x33\", \"0xFF\"]"

#define CFG_N_rssa_device_id                    "rssa_device_id"
#define CFG_V_rssa_device_id                    "[\"0x00\", \"0x48\"]"

#define CFG_N_RSSD_LOG_filter                   "RSSD_LOG_filter"
#define CFG_C_RSSD_LOG_filter                   15

#define CFG_N_panel_type                        "panel_type"
#define CFG_N_extended_device_id                "extended_device_id"
#define CFG_V_extended_device_id                "[\"0x00\", \"0x30\", \"0x31\", \"0x32\", \"0x33\", \"0x40\", \"0x41\", \"0x42\", \"0x43\"]"

#define CFG_N_sync_panel_time                   "sync_panel_time"

#define CFG_N_extended_device_id_programming    "extended_device_id_programming"
#define CFG_N_enable_iaqualink                  "enable_iaqualink"
#define CFG_N_log_file                          "log_file"
#define CFG_N_mqtt_aq_topic                     "mqtt_aq_topic"
#define CFG_N_mqtt_server                       "mqtt_address"
#define CFG_N_mqtt_user                         "mqtt_user"
#define CFG_N_mqtt_passwd                       "mqtt_passwd"
#define CFG_N_mqtt_discovery_topic              "mqtt_discovery_topic"
#define CFG_N_mqtt_discovery_use_mac            "mqtt_discovery_use_mac"
#define CFG_N_mqtt_timed_update                 "mqtt_timed_update"

#define CFG_N_light_programming_mode            "light_programming_mode"
#define CFG_N_light_programming_initial_on      "light_programming_initial_on"
#define CFG_N_light_programming_initial_off     "light_programming_initial_off"
#define CFG_N_light_programming_advance_mode    "light_programming_advance_mode"
#define CFG_N_override_freeze_protect           "override_freeze_protect"
#define CFG_N_pda_sleep_mode                    "pda_sleep_mode"
#define CFG_N_convert_mqtt_temp                 "mqtt_convert_temp_to_c"

#define CFG_N_report_zero_spa_temp              "report_zero_spa_temp"
#define CFG_N_report_zero_pool_temp             "report_zero_pool_temp"
#define CFG_N_read_RS485_devmask                "read_RS485_devmask"
#define CFG_N_use_panel_aux_labels              "use_panel_aux_labels"
#define CFG_N_force_swg                         "force_swg"
#define CFG_N_force_ps_setpoints                "force_ps_setpoints"
#define CFG_N_force_frzprotect_setpoints        "force_frzprotect_setpoints"
#define CFG_N_force_chem_feeder                 "force_chem_feeder"
#define CFG_N_force_chiller                     "force_chiller"
#define CFG_N_display_warnings_web              "display_warnings_web"
#define CFG_N_log_protocol_packets              "log_protocol_packets"
#define CFG_N_device_pre_state                  "device_pre_state"

#define CFG_N_read_RS485_swg                    "read_RS485_swg"
#define CFG_N_read_RS485_ePump                  "read_RS485_ePump"
#define CFG_N_read_RS485_vsfPump                "read_RS485_vsfPump"
#define CFG_N_read_RS485_JXi                    "read_RS485_JXi"
#define CFG_N_read_RS485_LX                     "read_RS485_LX"
#define CFG_N_read_RS485_ChemLink               "read_RS485_ChemLink"
#define CFG_N_read_RS485_ChemAnalyzer           "read_RS485_TruSense"
#define CFG_N_read_RS485_iAqualink              "read_RS485_iAqualink"
#define CFG_N_read_RS485_HeatPump               "read_RS485_HeatPump"


#define CFG_N_enable_scheduler                  "enable_scheduler"

#define CFG_N_event_check_poweron               "event_poweron_check_pump"
#define CFG_N_event_check_freezeprotectoff      "event_freezeprotectoff_check_pump"
#define CFG_N_event_check_boostoff              "event_boostoff_check_pump"
#define CFG_N_event_check_pumpon_hour           "event_check_pumpon_hour"
#define CFG_N_event_check_pumpoff_hour         "event_check_pumpoff_hour"
#define CFG_N_event_check_usecron               "event_check_use_scheduler_times"

#define CFG_N_event_check_booston_device        "event_booston_check_device"

#define CFG_N_ftdi_low_latency                  "ftdi_low_latency"
#define CFG_N_rs485_frame_delay                 "rs485_frame_delay"

#define CFG_N_save_debug_log_masks              "save_debug_log_masks"
#define CFG_N_save_light_programming_value      "save_light_programming_value"


//#define CFG_V_UOM "[\"°C\", \"°F\", \"K\", \"Hz\", \"GHz\", \"Pa\", \"0x41\", \"hPa\", \"bar\", \"mbar\", \"inHg\", \"psi\", \"L\", \"mL\", \"m³\", \"ft³\", \"fl. oz.\", \"m³/h\", \"ft³/m\"]"

#endif