#pragma once
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>

#define NUMBER_OF_MODELS_PROTO 51
#define NUMBER_OF_TOPICS_PROTO 127
#define NUMBER_OF_TOPICS_EXTRA_PROTO 6
#define NUMBER_OF_OPT_TOPICS_PROTO 7
#define MAX_TOPIC_LEN_PROTO 42

int getBit1(uint8_t input);
int getBit1and2(uint8_t input);
int getBit3and4(uint8_t input);
int getBit5and6(uint8_t input);
int getBit7and8(uint8_t input);
int getBit3and4and5(uint8_t input);
int getLeft5bits(uint8_t input);
int getRight3bits(uint8_t input);
int getIntMinus1(uint8_t input);
int getIntMinus128(uint8_t input);
float getIntMinus1Div5(uint8_t input);
float getIntMinus1Div50(uint8_t input);
int getIntMinus1Times10(uint8_t input);
int getIntMinus1Times50(uint8_t input);
int getFirstByte(uint8_t input);
int getSecondByte(uint8_t input);
int getWord(uint8_t hi, uint8_t low);
int getUintt16(uint8_t input1, uint8_t input2);

int getPower(uint8_t input);
int getOpMode(uint8_t input);
int getModel(std::vector<uint8_t> &data, uint8_t index);
int getBivalent(uint8_t input);
float getPumpFlow(uint8_t input1, uint8_t input2);
float getFractional(uint8_t input, uint8_t shift);
std::string getErrorInfo(uint8_t errorType, uint8_t errorNumber);

bool getBoolState(uint8_t input);
std::string getTextState(const char **array, int index);

static const char *DisabledEnabled[] = {"2", "Disabled", "Enabled"};
static const char *BlockedFree[] = {"2", "Blocked", "Free"};
static const char *OffOn[] = {"2", "Off", "On"};
static const char *InactiveActive[] = {"2", "Inactive", "Active"};
static const char *PumpFlowRateMode[] = {"2", "DeltaT", "Max flow"};
static const char *HolidayState[] = {"3", "Off", "Scheduled", "Active"};
static const char *OpModeDesc[] = {"9", "Heat", "Cool", "Auto(heat)", "DHW", "Heat+DHW", "Cool+DHW", "Auto(heat)+DHW", "Auto(cool)", "Auto(cool)+DHW"};
static const char *Powerfulmode[] = {"4", "Off", "30min", "60min", "90min"};
static const char *Quietmode[] = {"4", "Off", "Level 1", "Level 2", "Level 3"};
static const char *Valve[] = {"2", "Room", "DHW"};
static const char *MixingValve[] = {"4", "Off", "Increase","Nothing","Decrease"};
static const char *ZonesState[] = {"3", "Zone1 active", "Zone2 active", "Zone1 and zone2 active"};
static const char *HeatCoolModeDesc[] = {"2", "Comp. Curve", "Direct"};
static const char *SolarModeDesc[] = {"3", "Disabled", "Buffer", "DHW"};
static const char *ZonesSensorType[] = {"4", "Water Temperature", "External Thermostat", "Internal Thermostat", "Thermistor"};
static const char *LiquidType[] = {"2", "Water", "Glycol"};
static const char *ExtPadHeaterType[] = {"3", "Disabled", "Type-A","Type-B"};
static const char *Bivalent[] = {"6", "Off", "Alternativ", "A-Off", "Parallel", "P-Off", "Parallel Advanced"};

static const char *ModelNames[] =
{
  "51", //string representation of number of known models (last model number + 1)
  "WH-MDC05H3E5", //0
  "WH-MDC07H3E5", //1
  "IDU:WH-SXC09H3E5, ODU:WH-UX09HE5", //2
  "IDU:WH-SDC09H3E8, ODU:WH-UD09HE8", //3
  "IDU:WH-SXC09H3E8, ODU:WH-UX09HE8", //4
  "IDU:WH-SXC12H9E8, ODU:WH-UX12HE8", //5
  "IDU:WH-SXC16H9E8, ODU:WH-UX16HE8", //6
  "IDU:WH-SDC05H3E5, ODU:WH-UD05HE5", //7
  "IDU:WH-SDC0709J3E5, ODU:WH-UD09JE5",  //8
  "WH-MDC05J3E5", //9
  "WH-MDC09H3E5", //10
  "WH-MXC09H3E5", //11
  "IDU:WH-ADC0309J3E5, ODU:WH-UD09JE5", //12
  "IDU:WH-ADC0916H9E8, ODU:WH-UX12HE8", //13
  "IDU:WH-SQC09H3E8, ODU:WH-UQ09HE8", //14
  "IDU:WH-SDC09H3E5, ODU:WH-UD09HE5", //15
  "IDU:WH-ADC0309H3E5, ODU:WH-UD09HE5", //16
  "IDU:WH-ADC0309J3E5, ODU:WH-UD05JE5", //17
  "IDU:WH-SDC0709J3E5, ODU:WH-UD07JE5", //18
  "IDU:WH-SDC07H3E5-1, ODU:WH-UD07HE5-1", //19
  "WH-MDC07J3E5", //20
  "WH-MDC09J3E5", //21
  "IDU:WH-SDC0305J3E5, ODU:WH-UD05JE5", //22
  "WH-MXC09J3E8", //23
  "WH-MXC12J9E8", //24
  "IDU:WH-ADC1216H6E5, ODU:WH-UD12HE5", //25
  "IDU:WH-ADC0309J3E5C, ODU:WH-UD07JE5", //26
  "WH-MDC07J3E5", //27
  "WH-MDC05J3E5", //28
  "IDU:WH-UQ12HE8, ODU:WH-SQC12H9E8", //29
  "IDU:WH-SXC12H6E5, ODU:WH-UX12HE5", //30
  "WH-MDC09J3E5", //31
  "WH-MXC09J3E5", //32
  "IDU:WH-ADC1216H6E5C ODU:WH-UD12HE5", //33
  "IDU:WH-ADC0509L3E5 ODU:WH-WDG07LE5", //34
  "IDU:WH-SXC09H3E8 ODU:WH-UX09HE8", //35
  "IDU:WH-ADC0309K3E5AN ODU:WH-UDZ07KE5", //36
  "IDU:WH-SDC0309K3E5 ODU:WH-UDZ05KE5", //37
  "IDU:WH-SDC0509L3E5 ODU:WH-WDG09LE5", //38
  "IDU:WH-SDC12H9E8 ODU:WH-UD12HE8", //39
  "IDU:WH-SDC0309K3E5, ODU:WH-UDZ07KE5", //40
  "IDU:WH-ADC0916H9E8, ODU:WH-UX16HE8", //41
  "IDU:WH-ADC0912H9E8, ODU:WH-UX12HE8", //42
  "WH-MXC16J9E8", //43
  "WH-MXC12J6E5", //44
  "IDU:WH-SQC09H3E8, ODU:WH-UQ09HE8", //45
  "IDU:WH-ADC0309K3E5 ODU:WH-UDZ09KE5", //46
  "IDU:WH-ADC0916H9E8, ODU:WH-UX12HE8", //47
  "IDU:WH-SDC0509L3E5 ODU:WH-WDG07LE5", //48
  "IDU:WH-SXC09H3E5, ODU:WH-UX09HE5", //49
  "IDU:WH-SXC12H9E8, ODU:WH-UX12HE8", //50
};

// stores the bytes #129 to #138 of known models in the same order as the ModelNames above
static const uint8_t KnownModels[NUMBER_OF_MODELS_PROTO][10] =
{
  0xE2, 0xCF, 0x0B, 0x13, 0x33, 0x32, 0xD1, 0x0C, 0x16, 0x33, //0
  0xE2, 0xCF, 0x0B, 0x14, 0x33, 0x42, 0xD1, 0x0B, 0x17, 0x33, //1
  0xE2, 0xCF, 0x0D, 0x77, 0x09, 0x12, 0xD0, 0x0B, 0x05, 0x11, //2
  0xE2, 0xCF, 0x0C, 0x88, 0x05, 0x12, 0xD0, 0x0B, 0x97, 0x05, //3
  0xE2, 0xCF, 0x0D, 0x85, 0x05, 0x12, 0xD0, 0x0C, 0x94, 0x05, //4
  0xE2, 0xCF, 0x0D, 0x86, 0x05, 0x12, 0xD0, 0x0C, 0x95, 0x05, //5
  0xE2, 0xCF, 0x0D, 0x87, 0x05, 0x12, 0xD0, 0x0C, 0x96, 0x05, //6
  0xE2, 0xCE, 0x0D, 0x71, 0x81, 0x72, 0xCE, 0x0C, 0x92, 0x81, //7
  0x62, 0xD2, 0x0B, 0x43, 0x54, 0x42, 0xD2, 0x0B, 0x72, 0x66, //8
  0xC2, 0xD3, 0x0B, 0x33, 0x65, 0xB2, 0xD3, 0x0B, 0x94, 0x65, //9
  0xE2, 0xCF, 0x0B, 0x15, 0x33, 0x42, 0xD1, 0x0B, 0x18, 0x33, //10
  0xE2, 0xCF, 0x0B, 0x41, 0x34, 0x82, 0xD1, 0x0B, 0x31, 0x35, //11
  0x62, 0xD2, 0x0B, 0x45, 0x54, 0x42, 0xD2, 0x0B, 0x47, 0x55, //12
  0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0D, 0x95, 0x05, //13
  0xE2, 0xCF, 0x0B, 0x82, 0x05, 0x12, 0xD0, 0x0C, 0x91, 0x05, //14
  0xE2, 0xCF, 0x0C, 0x55, 0x14, 0x12, 0xD0, 0x0B, 0x15, 0x08, //15
  0xE2, 0xCF, 0x0C, 0x43, 0x00, 0x12, 0xD0, 0x0B, 0x15, 0x08, //16
  0x62, 0xD2, 0x0B, 0x45, 0x54, 0x32, 0xD2, 0x0C, 0x45, 0x55, //17
  0x62, 0xD2, 0x0B, 0x43, 0x54, 0x42, 0xD2, 0x0C, 0x46, 0x55, //18
  0xE2, 0xCF, 0x0C, 0x54, 0x14, 0x12, 0xD0, 0x0B, 0x14, 0x08, //19
  0xC2, 0xD3, 0x0B, 0x34, 0x65, 0xB2, 0xD3, 0x0B, 0x95, 0x65, //20
  0xC2, 0xD3, 0x0B, 0x35, 0x65, 0xB2, 0xD3, 0x0B, 0x96, 0x65, //21
  0x62, 0xD2, 0x0B, 0x41, 0x54, 0x32, 0xD2, 0x0C, 0x45, 0x55, //22
  0x32, 0xD4, 0x0B, 0x87, 0x84, 0x73, 0x90, 0x0C, 0x84, 0x84, //23
  0x32, 0xD4, 0x0B, 0x88, 0x84, 0x73, 0x90, 0x0C, 0x85, 0x84, //24
  0xE2, 0xCF, 0x0B, 0x75, 0x09, 0x12, 0xD0, 0x0C, 0x06, 0x11, //25
  0x42, 0xD4, 0x0B, 0x83, 0x71, 0x42, 0xD2, 0x0C, 0x46, 0x55, //26
  0xC2, 0xD3, 0x0C, 0x34, 0x65, 0xB2, 0xD3, 0x0B, 0x95, 0x65, //27
  0xC2, 0xD3, 0x0C, 0x33, 0x65, 0xB2, 0xD3, 0x0B, 0x94, 0x65, //28
  0xE2, 0xCF, 0x0B, 0x83, 0x05, 0x12, 0xD0, 0x0D, 0x92, 0x05, //29
  0xE2, 0xCF, 0x0C, 0x78, 0x09, 0x12, 0xD0, 0x0B, 0x06, 0x11, //30
  0xC2, 0xD3, 0x0C, 0x35, 0x65, 0xB2, 0xD3, 0x0B, 0x96, 0x65, //31
  0x32, 0xD4, 0x0B, 0x99, 0x77, 0x62, 0x90, 0x0B, 0x01, 0x78, //32
  0x42, 0xD4, 0x0B, 0x15, 0x76, 0x12, 0xD0, 0x0B, 0x10, 0x11, //33
  0xE2, 0xD5, 0x0C, 0x29, 0x99, 0x83, 0x92, 0x0C, 0x28, 0x98, //34
  0xE2, 0xCF, 0x0D, 0x85, 0x05, 0x12, 0xD0, 0x0E, 0x94, 0x05, //35
  0xE2, 0xD5, 0x0D, 0x36, 0x99, 0x02, 0xD6, 0x0F, 0x67, 0x95, //36
  0xE2, 0xD5, 0x0B, 0x08, 0x95, 0x02, 0xD6, 0x0E, 0x66, 0x95, //37
  0xE2, 0xD5, 0x0B, 0x34, 0x99, 0x83, 0x92, 0x0C, 0x29, 0x98, //38
  0xE2, 0xCF, 0x0C, 0x89, 0x05, 0x12, 0xD0, 0x0C, 0x98, 0x05, //39
  0xE2, 0xD5, 0x0B, 0x08, 0x95, 0x02, 0xD6, 0x0E, 0x67, 0x95, //40
  0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0C, 0x96, 0x05, //41
  0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0E, 0x95, 0x05, //42
  0x32, 0xD4, 0x0B, 0x89, 0x84, 0x73, 0x90, 0x0C, 0x86, 0x84, //43
  0x32, 0xD4, 0x0B, 0x00, 0x78, 0x62, 0x90, 0x0B, 0x02, 0x78, //44
  0xE2, 0xCF, 0x0B, 0x82, 0x05, 0x12, 0xD0, 0x0D, 0x91, 0x05, //45
  0xE2, 0xD5, 0x0D, 0x99, 0x94, 0x02, 0xD6, 0x0D, 0x68, 0x95, //46
  0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0C, 0x95, 0x05, //47
  0xE2, 0xD5, 0x0B, 0x34, 0x99, 0x83, 0x92, 0x0C, 0x28, 0x98, //48
  0xE2, 0xCF, 0x0D, 0x77, 0x09, 0x12, 0xD0, 0x0C, 0x05, 0x11, //49
  0xE2, 0xCF, 0x0D, 0x86, 0x05, 0x12, 0xD0, 0x0E, 0x95, 0x05, //50
};
