#ifndef RDMHANDLER_H__
#define RDMHANDLER_H__

#include <stdbool.h>
#include <stdint.h>

#include "rdmlib.h"

typedef struct
{
	rdm_response_t response;
	rdm_nack_reasoncodes_t reason;
} rdm_answer_t;

#ifdef RDM_SUPPORT_MINIMAL
#define RDM_SUPPORT_DISCOVERY
#define RDM_SUPPORT_REQUIRED
#define RDM_SUPPORT_CUSTOM_IQ
#endif

#ifdef RDM_SUPPORT_IQ
#define RDM_SUPPORT_REQUIRED
#define RDM_SUPPORT_CUSTOM_IQ
#define RDM_SUPPORT_BASIC
#endif

#ifdef RDM_SUPPORT_FULL
#define RDM_SUPPORT_CUSTOM_SERVICEHOURS
#define RDM_SUPPORT_CUSTOM_LEDCAL
#define RDM_SUPPORT_EXTENDED
#define RDM_SUPPORT_DIMMER
#define RDM_SUPPORT_SELFTEST
#define RDM_SUPPORT_LAMP
#define RDM_SUPPORT_DISCOVERY
#define RDM_SUPPORT_CUSTOM_IQ
#define RDM_SUPPORT_BASIC
#define RDM_SUPPORT_CUSTOM_RDMDFU
#endif

#define RDMDATALENGTHMAX 230

#define RDM_MAX_SLOTINFO (RDMDATALENGTHMAX / sizeof(rdm_slot_info_get_response_array_t))

void rdm_init(const uint8_t *_rdm_id,
			  void (*rdm_answer_callback)(const uint8_t *msg, uint16_t length, bool sentBreak, uint8_t _id));
void rdm_setRdmId(const uint8_t *_rdm_id);
void rdm_decodeMessage(const uint8_t *msg, uint16_t length, uint8_t _id);

#ifdef RDM_SUPPORT_PROXY
void rdm_setProxyRdmIds(const uint8_t *_rdm_ids, uint8_t length, uint16_t _averageResponseTime100ms,
						void (*rdm_proxy_transmit_callback)(const uint8_t *data, uint16_t length, uint8_t _id));
#endif

#if defined(RDM_SUPPORT_QUEUED_MESSAGES) || defined(RDM_SUPPORT_PROXY)
void rdm_registerQueueCallbacks(void (*rdm_queue_count_callback)(uint8_t *rdmId, uint8_t *responseQueueCount,
																 uint8_t _id),
								bool (*rdm_proxy_queue_callback)(uint8_t *rdmId, uint8_t *data, uint16_t *length,
																 uint8_t _id));
#endif

#ifdef RDM_SUPPORT_REQUIRED
void RdmExtGetDeviceInfo(rdm_answer_t *rdmImp, rdm_device_info_get_response_t *responseBuf);
void RdmExtGetSoftwareVersionLabel(rdm_answer_t *rdmImp, rdm_softwareversion_label_get_response_t *responseBuf);
void RdmExtGetIdentify(rdm_answer_t *rdmImp, rdm_identify_device_get_response_t *responseBuf);
#endif

#ifdef RDM_SUPPORT_BASIC
void RdmExtGetFactoryDefaults(rdm_answer_t *rdmImp, rdm_factory_default_get_response_t *responseBuf);
void RdmExtGetProductDetail(rdm_answer_t *rdmImp, rdm_product_detail_id_get_response_t *responseBuf);
void RdmExtGetDeviceModelDescription(rdm_answer_t *rdmImp, rdm_device_model_description_get_response_t *responseBuf);
void RdmExtGetManufacturerLabel(rdm_answer_t *rdmImp, rdm_manufacturer_label_get_response_t *responseBuf);
void RdmExtGetDeviceLabel(rdm_answer_t *rdmImp, rdm_device_label_get_response_t *responseBuf);
void RdmExtGetBootSoftwareVersionLabel(rdm_answer_t *rdmImp,
									   rdm_boot_softwareversion_label_get_response_t *responseBuf);
void RdmExtGetDmxPersonality(rdm_answer_t *rdmImp, rdm_dmx_personality_get_response_t *responseBuf);
void RdmExtGetDmxPersonalityDescription(rdm_answer_t *rdmImp,
										rdm_dmx_personality_description_get_response_t *responseBuf);
void RdmExtGetDmxStartaddress(rdm_answer_t *rdmImp, rdm_dmx_startaddress_get_response_t *responseBuf);
void RdmExtGetSensorDefinition(rdm_answer_t *rdmImp, rdm_sensor_defintion_get_response_t *responseBuf);
void RdmExtGetSensorValue(rdm_answer_t *rdmImp, rdm_sensor_value_get_response_t *responseBuf);
void RdmExtGetDeviceHours(rdm_answer_t *rdmImp, rdm_device_hours_get_response_t *responseBuf);
void RdmExtGetLampHours(rdm_answer_t *rdmImp, rdm_lamphours_get_response_t *responseBuf);
void RdmExtGetLampStrikes(rdm_answer_t *rdmImp, rdm_lampstrike_get_response_t *responseBuf);
void RdmExtGetLampState(rdm_answer_t *rdmImp, rdm_lampstate_get_response_t *responseBuf);
void RdmExtGetDevicePowerCycles(rdm_answer_t *rdmImp, rdm_device_power_cycle_get_response_t *responseBuf);

void RdmExtGetPowerState(rdm_answer_t *rdmImp, rdm_power_state_get_response_t *responseBuf);
void RdmExtGetSupportedParameter(rdm_answer_t *rdmImp, uint16_t *responseBuf, uint8_t *pidCount);
void RdmExtGetParameterDescription(rdm_answer_t *rdmImp, rdm_parameter_description_get_response_t *responseBuf);
void RdmExtGetCustomPid(uint16_t pid, uint8_t *msg, uint16_t pdl, rdm_answer_t *rdmImp, uint8_t *responseBuf,
						uint16_t *responseLength);
void RdmExtGetBootSoftwareID(rdm_answer_t *rdmImp, uint32_t *responseBootSoftwareID);
#endif

#ifdef RDM_SUPPORT_CUSTOM_IQ
void RdmExtGetIq(rdm_answer_t *rdmImp, rdm_iq_get_response_t *responseBuf);
void RdmExtGetCustomError(rdm_answer_t *rdmImp, rdm_custom_label_get_response_t *responseBuf);
void RdmExtGetCustomWarning(rdm_answer_t *rdmImp, rdm_custom_label_get_response_t *responseBuf);
#endif


#ifdef RDM_SUPPORT_SELFTEST
void RdmExtGetPerformSelftest(rdm_answer_t *rdmImp, rdm_perform_selftest_get_response_t *responseBuf);
void RdmExtGetSelfTestDescription(rdm_answer_t *rdmImp, rdm_selftest_description_get_response_t *responseBuf);
#endif

#ifdef RDM_SUPPORT_LAMP
void RdmExtGetLampOnMode(rdm_answer_t *rdmImp, rdm_lamp_on_mode_response_t *responseBuf);
#endif

#ifdef RDM_SUPPORT_EXTENDED
void RdmExtGetLanguageCapabilities(rdm_answer_t *rdmImp, uint8_t *responseBuf, uint8_t *languageCounter);
void RdmExtGetLanguage(rdm_answer_t *rdmImp, rdm_language_get_response_t *responseBuf);
void RdmExtGetSlotInfo(rdm_answer_t *rdmImp, rdm_slot_info_get_response_array_t *responseBuf, uint8_t *slotCount);
void RdmExtGetSlotDescription(rdm_answer_t *rdmImp, rdm_slot_desc_get_response_t *responseBuf);
void RdmExtGetDefaultSlotValue(rdm_answer_t *rdmImp, rdm_slot_default_get_response_array_t *responseBuf,
							   uint8_t *slotCount);
void RdmExtGetDisplayInvert(rdm_answer_t *rdmImp, rdm_display_invert_get_response_t *responseBuf);
void RdmExtGetDisplayLevel(rdm_answer_t *rdmImp, uint8_t *responseBuf);
void RdmExtGetPanInvert(rdm_answer_t *rdmImp, bool *responseBuf);
void RdmExtGetTiltInvert(rdm_answer_t *rdmImp, bool *responseBuf);
void RdmExtGetRealTimeClock(rdm_answer_t *rdmImp, uint64_t *responseBuf);
void RdmExtGetPresetPlayback(rdm_answer_t *rdmImp, rdm_preset_playback_response_t *responseBuf);
#endif

#ifdef RDM_SUPPORT_DIMMER
void RdmExtGetDimmerInfo(rdm_answer_t *rdmImp, rdm_dimmer_info_response_t *responseBuf);
void RdmExtGetMinimumLevel(rdm_answer_t *rdmImp, rdm_minimum_response_t *responseBuf);
void RdmExtGetMaximumLevel(rdm_answer_t *rdmImp, uint16_t *responseMaximumLevel);
void RdmExtGetCurve(rdm_answer_t *rdmImp, rdm_curve_response_t *responseBuf);
void RdmExtGetCurveDescription(rdm_answer_t *rdmImp, rdm_curve_description_response_t *responseBuf);
void RdmExtGetOutputResponseTime(rdm_answer_t *rdmImp, rdm_output_response_time_response_t *responseBuf);
void RdmExtGetOutputResponseTimeDescription(rdm_answer_t *rdmImp,
											rdm_output_response_time_description_response_t *responseBuf);
void RdmExtGetModulationFrequency(rdm_answer_t *rdmImp, rdm_modulation_frequency_response_t *responseBuf);
void RdmExtGetModulationFrequencyDescription(rdm_answer_t *rdmImp,
											 rdm_modulation_frequency_description_response_t *responseBuf);
#endif

#ifdef RDM_SUPPORT_CUSTOM_LEDCAL
void RdmExtGetCustomAdjustLedCalibrationData(rdm_answer_t *rdmImp, rdm_adjustledcalibration_get_response_t *responseBuf,
											 rdm_adjustledcalibration_colorinfos_get_response_t *responseBufColorInfos);
void RdmExtGetCustomAdjustLedCalibrationDebug(rdm_answer_t *rdmImp,
											  rdm_adjustledcalibration_debug_get_response_t *responseBuf);
#endif

#ifdef RDM_SUPPORT_CUSTOM_SERVICEHOURS
void RdmExtGetCustomServiceHours(rdm_answer_t *rdmImp, uint32_t *responseBuf);
#endif

#ifdef RDM_SUPPORT_COLORCONVERTER
void RdmExtGetColorConverterLicense(rdm_answer_t *rdmImp, uint8_t *iv, uint8_t *responseBuf, uint8_t *responseLength);
void RdmExtGetColorConverterCalibration(rdm_answer_t *rdmImp, uint8_t *responseLedCount, uint8_t *responseDieCount);
void RdmExtGetColorConverterControl(rdm_answer_t *rdmImp, uint16_t *responseBuf, uint8_t *length);
#endif

#ifdef RDM_SUPPORT_REQUIRED
void RdmExtSetIdentify(rdm_answer_t *rdmImp, bool set);
#endif

#ifdef RDM_SUPPORT_BASIC
void RdmExtSetFactoryDefaults(rdm_answer_t *rdmImp);
void RdmExtSetDeviceLabel(rdm_answer_t *rdmImp, char *label, uint8_t labelLength);
void RdmExtSetDmxPersonality(rdm_answer_t *rdmImp, uint8_t personality);
void RdmExtSetDmxStartaddress(rdm_answer_t *rdmImp, uint16_t dmxStartAddress);
void RdmExtSetResetDevice(rdm_answer_t *rdmImp, rdm_reset_t reset);
void RdmExtSetPowerState(rdm_answer_t *rdmImp, rdm_powerstate_t powerState);
void RdmExtSetCustomPid(rdm_answer_t *rdmImp, uint16_t pid, uint8_t *data, uint16_t pdl);
#endif

#ifdef RDM_SUPPORT_CUSTOM_IQ
void RdmExtSetIqInputSource(rdm_answer_t *rdmImp, rdm_iq_inputsource_t inputSource);
void RdmExtSetIqInputState(rdm_answer_t *rdmImp, rdm_iq_set_input_state_t inputState);
void RdmExtSetIqPopup(rdm_answer_t *rdmImp, rdm_iq_popup_t popup);
void RdmExtSetIqEmergencyMode(rdm_answer_t *rdmImp, bool emergencyMode);
void RdmExtSetIqBatteryRuntime(rdm_answer_t *rdmImp, rdm_iq_battery_runtime_t runTime);
void RdmExtSetIqAntitheftMode(rdm_answer_t *rdmImp, rdm_iq_antitheft_t antitheft);
#endif

#ifdef RDM_SUPPORT_SELFTEST
void RdmExtSetPerformSelftest(rdm_answer_t *rdmImp, uint8_t selftest);
#endif

#ifdef RDM_SUPPORT_CUSTOM_LEDCAL
void RdmExtSetCustomAdjustLedCalibrationSend(rdm_answer_t *rdmImp, rdm_adjustledcalibration_send_set_t set,
											 uint8_t *data, uint8_t chunkLength,
											 custom_adjust_cal_send_response_t *response);
void RdmExtSetCustomAdjustLedCalibrationData(rdm_answer_t *rdmImp, rdm_adjustledcalibration_set_t responseBuf);
#endif

#ifdef RDM_SUPPORT_CUSTOM_SERVICEHOURS
void RdmExtSetCustomServiceHours(rdm_answer_t *rdmImp, uint32_t counter);
#endif

#ifdef RDM_SUPPORT_EXTENDED
void RdmExtSetLanguage(rdm_answer_t *rdmImp, rdm_language_set_t language);
void RdmExtSetDisplayInvert(rdm_answer_t *rdmImp, rdm_display_invert_t displayInvert);
void RdmExtSetDisplayLevel(rdm_answer_t *rdmImp, uint8_t displayLevel);
void RdmExtSetPanInvert(rdm_answer_t *rdmImp, bool invert);
void RdmExtSetTiltInvert(rdm_answer_t *rdmImp, bool invert);
void RdmExtSetCapturePreset(rdm_answer_t *rdmImp, rdm_capture_preset_set_t preset);
void RdmExtSetRealTimeClock(rdm_answer_t *rdmImp, uint64_t rtc);
void RdmExtSetPresetPlayback(rdm_answer_t *rdmImp, rdm_preset_playback_response_t preset);
#endif

#ifdef RDM_SUPPORT_DIMMER
void RdmExtSetMinimumLevel(rdm_answer_t *rdmImp, rdm_minimum_response_t minimumLevel);
void RdmExtSetMaximumLevel(rdm_answer_t *rdmImp, uint16_t maximumLevel);
void RdmExtSetCurve(rdm_answer_t *rdmImp, uint8_t curve);
void RdmExtSetOutputResponseTime(rdm_answer_t *rdmImp, uint8_t responseTime);
void RdmExtSetModulationFrequency(rdm_answer_t *rdmImp, uint8_t modulationFrequency);
#endif

#ifdef RDM_SUPPORT_LAMP
void RdmExtSetLampOnMode(rdm_answer_t *rdmImp, rdm_lamp_on_mode_t lamp_mode);
#endif

#ifdef RDM_SUPPORT_COLORCONVERTER
void RdmExtSetColorConverterLicense(rdm_answer_t *rdmImp, rdm_colorconverter_license_t key);
void RdmExtSetColorConverterCalibration(rdm_answer_t *rdmImp, rdm_colorconverter_cal_command_t command,
										uint16_t dataOffset, uint16_t *calData, uint8_t length);
void RdmExtSetColorConverterControl(rdm_answer_t *rdmImp, uint8_t ledIndex, uint8_t dieIndex, uint16_t dimmerValue);

#endif

#endif
