// (CVN) - Candy Valley Network GmbH

#pragma once

#include <CoreMinimal.h>

// EXTERNAL INCLUDES
#include <TimerManager.h>
#include <UObject/StrongObjectPtr.h>

// INTERNAL INCLUDES

#include "LovenseTypes.generated.h"



namespace LovenseIntegration {
	// ReSharper disable CppVariableCanBeMadeConstexpr - FString constructors are not constexpr, so we can't make these constexpr either.
	/** @brief File path+name (excluding file extension) for the lovense config relative to the generated config directory. Value is "Lovense/Lovense". */
	LOVENSEINTEGRATION_API extern const FString configFileName;
	/** @brief The config section the config values will be stored under. Value is "Lovense.Lovense". */
	LOVENSEINTEGRATION_API extern const FString configSectionName;
	/**
	 * @brief Config value key name for the StartWithLovenseActive setting.
	 * \n This setting is a bool value. Default is false.
	 * \n If true, lovense will be started on StartupModule(). Defaults to false.
	 * \n Value is "StartWithLovenseActive".
	 */
	LOVENSEINTEGRATION_API extern const FString configStartWithLovenseActiveKeyName;
	/**
	 * @brief Deprecated. Superseded by configDeviceIpOverrideKeyName.
	 * Only used to upgrade config.
	 */
	[[deprecated("Use configDeviceIpOverrideKeyName instead.")]]
	LOVENSEINTEGRATION_API extern const FString configMobileDeviceIpOverrideKeyName;
	/**
	 * @brief Deprecated. Superseded by configDevicePortOverrideKeyName.
	 * Only used to upgrade config.
	 */
	[[deprecated("Use configDevicePortOverrideKeyName instead.")]]
	LOVENSEINTEGRATION_API extern const FString configMobileDevicePortOverrideKeyName;
	/**
	 * @brief Config value key name for the DeviceIpOverride setting.
	 * \n This setting is a string value. Default is TEXT("").
	 * \n If this string contains a valid ip, it will be used to connect with the adapters.
	 * \n Value is "DeviceIpOverride".
	 */
	LOVENSEINTEGRATION_API extern const FString configDeviceIpOverrideKeyName;
	/**
	 * @brief Config value key name for the DevicePortOverride setting.
	 * \n This setting is a string value. Default is TEXT("").
	 * \n If this string contains a valid port, it will be used to connect with the adapters.
	 * \n Value is "DevicePortOverride".
	 */
	LOVENSEINTEGRATION_API extern const FString configDevicePortOverrideKeyName;
	/**
	 * @brief Config value key name for the DevicePlatformIsMobile setting.
	 * \n This setting is a bool value. Default is false.
	 * \n Value is "DevicePlatformIsMobile".
	 */
	LOVENSEINTEGRATION_API extern const FString configDevicePlatformIsMobileKeyName;
	/**
	 * @brief Config value key name for the ToyDelay setting.
	 * \n This setting is an integer value. Default is 500. Range is 0-2000.
	 * \n The toy delay adjusts the start time for pattern generation based on animations. (See ULovenseToyAnimationControlComponent)
	 * \n Value is "ToyDelay".
	 */
	LOVENSEINTEGRATION_API extern const FString configToyDelayKeyName;
	/**
	 * @brief Config value key name for the ToyStrengthMultiplier setting.
	 * \n This setting is a float value. Default is 1.0f. Range if 0.0f-1.0f.
	 * \n The toy strength multiplier scales the speed values before commands are sent.
	 * \n Value is "ToyStrengthMultiplier".
	 */
	LOVENSEINTEGRATION_API extern const FString configToyStrengthMultiplierKeyName;
	/**
	 * @brief Config value key name for the ToyVibration setting.
	 * \n This setting is a bool value. Default is true.
	 * \n If false, vibration speed values will be set to 0 before commands are sent, so toys will not vibrate.
	 * \n Value is "ToyVibration".
	 */
	LOVENSEINTEGRATION_API extern const FString configToyVibrationKeyName;
	/**
	 * @brief Config value key name for the ToyRotation setting.
	 * \n This setting is a bool value. Default is true.
	 * \n If false, rotation speed values will be set to 0 before commands are sent, so toys will not rotate.
	 * \n Value is "ToyRotation".
	 */
	LOVENSEINTEGRATION_API extern const FString configToyRotationKeyName;
	/**
	 * @brief Config value key name for the ToyAir setting.
	 * \n This setting is a bool value. Default is true.
	 * \n If false, air speed values will be set to 0 before commands are sent, so toys will not pump.
	 * \n Value is "ToyAir".
	 */
	LOVENSEINTEGRATION_API extern const FString configToyAirKeyName;
	/**
	 * @brief Config value key name for the ToyThrusting setting.
	 * \n This setting is a bool value. Default is true.
	 * \n If false, thrusting speed values will be set to 0 before commands are sent, so toys will not thrust.
	 * \n Value is "ToyThrusting".
	 */
	LOVENSEINTEGRATION_API extern const FString configToyThrustingKeyName;
	/**
	 * @brief Config value key name for the ToySuction setting.
	 * \n This setting is a bool value. Default is true.
	 * \n If false, suction speed values will be set to 0 before commands are sent, so toys will not suck.
	 * \n Value is "ToySuction".
	 */
	LOVENSEINTEGRATION_API extern const FString configToySuctionKeyName;
	/**
	 * @brief Config value key name for the ToyFingering setting.
	 * \n This setting is a bool value. Default is true.
	 * \n If false, fingering speed values will be set to 0 before commands are sent, so toys will not finger.
	 * \n Value is "ToyFingering".
	 */
	LOVENSEINTEGRATION_API extern const FString configToyFingeringKeyName;
	// ReSharper restore CppVariableCanBeMadeConstexpr
}

UENUM(BlueprintType)
enum class ELovenseCommandType :uint8 {
	VIBRATE = 0,
	ROTATE = 1,
	PUMP = 2,
	THRUST = 3,
	SUCTION = 4,
	FINGERING = 5,
	VIBRATE1 = 6,
	VIBRATE2 = 7,
	VIBRATE3 = 8,
	DEPTH = 9,
	POSITION = 10,
};

UENUM(BlueprintType)
enum class ELovenseEventType :uint8 {
	VIBRATE = 0,
	ROTATE = 1,
	INFLATION = 2,
	THRUST = 3,
	SUCTION = 4,
	FINGERING = 5,
	SHAKE = 6,
	DEPTH = 7
};

UENUM(BlueprintType)
enum class ELovenseButtonEventType :uint8 {
	BUTTON_DOWN = 0,
	BUTTON_UP = 1,
	BUTTON_PRESSED = 2,
};

UCLASS(BlueprintType)
class UELovenseCommands :public UObject {
	GENERATED_BODY()

private:
	/** @brief The toy description of this toy. Holds (mostly) raw ILovenseAdapter::GetToys() HTTP request json data for this adapter. */
	UPROPERTY(BlueprintReadWrite, Category = "Lovense", Meta = (AllowPrivateAccess = "true"))
		ELovenseCommandType type;
	UPROPERTY(BlueprintReadWrite, Category = "Lovense", Meta = (AllowPrivateAccess = "true"))
		int value;
public:
	/*UELovenseCommands(const UELovenseCommands& copy) {
		type = copy.type;
		value = copy.value;
	}*/
	UELovenseCommands():type(ELovenseCommandType::VIBRATE),value(10) {
		
	}

	UELovenseCommands(const ELovenseCommandType& tp,int val)  {
		type = tp;
		value = val;
	}

	/*UELovenseCommands& operator=(const UELovenseCommands& Other) {
		if (this != &Other)
		{
			type = Other.type;
			value = Other.value;
		}
		return *this;
	}*/



	FORCEINLINE void SetCommandType(const ELovenseCommandType& tp) { this->type = tp; }
	FORCEINLINE void SetValue(const int& val) { this->value = val; }
	FORCEINLINE ELovenseCommandType GetCommandType() const {
		return type;
	}
	FORCEINLINE int GetValue() const {
		return value;
	}
	/*UFUNCTION(BlueprintCallable, Category = "Lovense")
	static UELovenseCommands* GenerateObject(ELovenseCommandType& tp,int va);*/
};

UCLASS(BlueprintType)
class UELovenseSolaceProCommands :public UELovenseCommands {
	GENERATED_BODY()

private:
	/** @brief The toy description of this toy. Holds (mostly) raw ILovenseAdapter::GetToys() HTTP request json data for this adapter. */
	UPROPERTY(BlueprintReadWrite, Category = "Lovense", Meta = (AllowPrivateAccess = "true"))
		int strokeLow;
	UPROPERTY(BlueprintReadWrite, Category = "Lovense", Meta = (AllowPrivateAccess = "true"))
		int strokeHigh;

public:
	
	UELovenseSolaceProCommands() :strokeLow(0), strokeHigh(100) {
		SetCommandType(ELovenseCommandType::POSITION);
	}

	FORCEINLINE void SetStrokeLow(const int& val) { this->strokeLow = val; }
	FORCEINLINE void SetStrokeHigh(const int& val) { this->strokeHigh = val; }
	
	FORCEINLINE void SetStrokeValue(const int& low, const int& height) {
		this->strokeLow = low;
		this->strokeHigh = height;
	}
	
	FORCEINLINE int GetStrokeLowValue() const {
		return strokeLow;
	}
	FORCEINLINE int GetStrokeHighValue() const {
		return strokeHigh;
	}
	/*UFUNCTION(BlueprintCallable, Category = "Lovense")
	static UELovenseCommands* GenerateObject(ELovenseCommandType& tp,int va);*/
};

UCLASS(BlueprintType)
class UEPositionPatternValue :public UObject {
	GENERATED_BODY()

private:
	/** @brief The toy description of this toy. Holds (mostly) raw ILovenseAdapter::GetToys() HTTP request json data for this adapter. */
	UPROPERTY(BlueprintReadWrite, Category = "Lovense", Meta = (AllowPrivateAccess = "true"))
		int time;
	UPROPERTY(BlueprintReadWrite, Category = "Lovense", Meta = (AllowPrivateAccess = "true"))
		int position;

public:


	FORCEINLINE void SetTime(const int& setTime) { this->time = setTime; }
	FORCEINLINE void SetPosition(const int& pos) { this->position = pos; }

	FORCEINLINE void SetValue(const int& setTime, const int& pos) {
		this->time = setTime;
		this->position = pos;
	}

	FORCEINLINE int GetTime() const {
		return time;
	}
	FORCEINLINE int GetPosition() const {
		return position;
	}
	/*UFUNCTION(BlueprintCallable, Category = "Lovense")
	static UELovenseCommands* GenerateObject(ELovenseCommandType& tp,int va);*/
};

UCLASS(BlueprintType)
class UELovenseEventsToy :public UObject {
	GENERATED_BODY()

private:
	/** @brief The toy description of this toy. Holds (mostly) raw ILovenseAdapter::GetToys() HTTP request json data for this adapter. */
	UPROPERTY(BlueprintReadWrite, Category = "Lovense", Meta = (AllowPrivateAccess = "true"))
	FString id;
	UPROPERTY(BlueprintReadWrite, Category = "Lovense", Meta = (AllowPrivateAccess = "true"))
	FString name;
	UPROPERTY(BlueprintReadWrite, Category = "Lovense", Meta = (AllowPrivateAccess = "true"))
	FString type;
	UPROPERTY(BlueprintReadWrite, Category = "Lovense", Meta = (AllowPrivateAccess = "true"))
	FString hVersion;
	UPROPERTY(BlueprintReadWrite, Category = "Lovense", Meta = (AllowPrivateAccess = "true"))
	int32 fVersion;
	UPROPERTY(BlueprintReadWrite, Category = "Lovense", Meta = (AllowPrivateAccess = "true"))
	FString nickName;
	UPROPERTY(BlueprintReadWrite, Category = "Lovense", Meta = (AllowPrivateAccess = "true"))
	int32 battery;
	UPROPERTY(BlueprintReadWrite, Category = "Lovense", Meta = (AllowPrivateAccess = "true"))
	bool connected;
public:
	/*UELovenseCommands(const UELovenseCommands& copy) {
		type = copy.type;
		value = copy.value;
	}*/
	UELovenseEventsToy() {

	}

	FORCEINLINE void SetId(const FString& newid) { this->id = newid; }
	FORCEINLINE void SetName(const FString& newname) { this->name = newname; }
	FORCEINLINE void SetType(const FString& newtype) { this->type = newtype; }
	FORCEINLINE void SetHVersion(const FString& newhVersion) { this->hVersion = newhVersion; }
	FORCEINLINE void SetFVersion(const int32& newfVersion) { this->fVersion = newfVersion; }
	FORCEINLINE void SetNickName(const FString& newnickName) { this->nickName = newnickName; }
	FORCEINLINE void SetBattery(const int32& newbattery) { this->battery = newbattery; }
	FORCEINLINE void SetConnected(const bool& newconnected) { this->connected = newconnected; }


	

	/*UELovenseCommands& operator=(const UELovenseCommands& Other) {
		if (this != &Other)
		{
			type = Other.type;
			value = Other.value;
		}
		return *this;
	}*/



	/*FORCEINLINE void SetCommandType(const ELovenseCommandType& tp) { this->type = tp; }
	FORCEINLINE void SetValue(const int& val) { this->value = val; }
	FORCEINLINE ELovenseCommandType GetCommandType() const {
		return type;
	}
	FORCEINLINE int GetValue() const {
		return value;
	}*/
	/*UFUNCTION(BlueprintCallable, Category = "Lovense")
	static UELovenseCommands* GenerateObject(ELovenseCommandType& tp,int va);*/
};


/**
 * @brief Container holding (mostly) raw HTTP request json data for a Lovense Toy instance.
 */
USTRUCT(BlueprintType)
struct LOVENSEINTEGRATION_API FLovenseToyDescription {
	GENERATED_USTRUCT_BODY()

	/** @brief The identifier for the toy. */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	FString id;

	/** @brief The name of the toy excluding the version, e.g. "Nora". Used in the UI. */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	FString name;

	/** @brief This value indicates whether the toy is connected to the Lovense app. 1 = Connected, 0 = Disconnected. Used in the UI. */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	int32 status;

	/**
	 * @brief Current battery status of the toy. Value is percentage charged, range is 0-100%.
	 * \n If battery status is unknown, value will be -1.
	 * \n Used in UI.
	 */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	int32 battery;

	/** @brief The firmware version of the toy. Is empty for Lovense Remote apps. */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	FString firmwareVersion;

	/** @brief User defined nickname for the toy. Empty if user has not defined a nickname. Used in the UI. */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	FString nickname;

	/** @brief The version of the toy, e.g. the "Edge 2" toy would have a version of 2. Empty if version is 1. Used in the UI. */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	FString version;

	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
		FString domain;


	FString ToString() const {
		FString output = TEXT("");
		FLovenseToyDescription::StaticStruct()->ExportText(output, this, nullptr, nullptr, 0, nullptr);
		return output;
	}

	FLovenseToyDescription() {
		this->id = TEXT("");
		this->name = TEXT("");
		this->status = 0;
		this->battery = 0;
		this->firmwareVersion = TEXT("");
		this->nickname = TEXT("");
		this->version = TEXT("");
		this->domain = TEXT("");
	}
};


/**
 * @brief Container holding (mostly) raw HTTP request json data for a Lovense App instance in the local network.
 */
USTRUCT(BlueprintType)
struct LOVENSEINTEGRATION_API FLovenseAdapterDescription {
	GENERATED_BODY()

	/**
	 * @brief The identifier for the adapter.
	 * \n For offline adapters the id wil be in this format: "[Api]_Offline[Platform]" e.g. "Remote_OfflineMobile" or "Connect_OfflineDesktop".
	 */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	FString deviceCode;

	/**
	 * @brief This value indicates whether the app is connected to the channel used by the Lovense server for forwarding instructions.
	 * \n (Whether the toys can be controlled through the service API)
	 * \n 1 = Connected, 0 = Disconnected.
	 * \n No connection will be attempted if 0.
	 */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	int32 online;

	/**
	 * @brief The domain used to communicate with the adapter.
	 * \n Adapter descriptions returned from the lovense servers have a domain string in this format: "X-X-X-X.lovense.club".
	 * \n Offline adapters have a direct IP as the domain.
	 */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	FString domain;

	/**
	 * @brief The https port. Currently unused.
	 * \n For the Lovense pc apps, this will always be 30010.
	 * \n For the Lovense Connect mobile apps, this will always be 34568.
	 * \n For the Lovense Remote mobile apps, this will be a dynamic port.
	 */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	int32 httpsPort;

	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	int32 httpPort;

	/**
	 * @brief The wss port. Currently unused.
	 * \n For the Lovense pc apps, this will always be 30110.
	 * \n For the Lovense Connect mobile apps, this will always be 30010.
	 * \n For the Lovense Remote mobile apps, this will be a dynamic port.
	 * \n Will be 0 for offline adapters.
	 */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	int32 wssPort;

	/** @brief The device platform of the adapter, e.g. "android" or "pc". Used in the adapter factory LovenseAdapter::CreateLovenseAdapter() and UI. */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	FString platform;

	/** @brief The version of the Lovense app. */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	FString appVersion;

	/** @brief The api of the adapter, e.g. "remote" or "connect". Used in the adapter factory LovenseAdapter::CreateLovenseAdapter() and UI. */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	FString appType;

	/**
	 * @brief Parsed toy descriptions from ILovenseAdapter::TryGetAdapterData() response.
	 * \n You usually want to use the toy descriptions in FLovenseGetToysResponseData stored in the respective adapters, as that has more complete toy data.
	 * \n Will contain a dummy toy for offline adapters.
	 */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	TArray<FLovenseToyDescription> toys;

	FString ToString() const {
		FString output = TEXT("");
		FLovenseAdapterDescription::StaticStruct()->ExportText(output, this, nullptr, nullptr, 0, nullptr);
		return output;
	}

	FLovenseAdapterDescription() {
		this->deviceCode = TEXT("");
		this->online = 0;
		this->domain = TEXT("");
		this->httpsPort = 0;
		this->httpPort = 0;
		this->wssPort = 0;
		this->platform = TEXT("");
		this->appVersion = TEXT("");
		this->appType = TEXT("");
		this->toys = TArray<FLovenseToyDescription>();
	}
};



/**
 * @brief Container holding (mostly) raw HTTP request json data from ILovenseAdapter::TryGetAdapterData() response.
 */
USTRUCT(BlueprintType)
struct LOVENSEINTEGRATION_API FLovenseGetAdaptersResponseData {
	GENERATED_BODY()

	/** @brief The response error code. 0 = success. */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	int32 code;

	/** @brief The response message. Will be either "ok" or "error". */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	FString message;

	/** @brief Parsed adapter descriptions from ILovenseAdapter::TryGetAdapterData() response + potential offline adapter descriptions. Should always have at least 1. */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	TArray<FLovenseAdapterDescription> adapters;

	/** @brief The raw json object string from ILovenseAdapter::TryGetAdapterData() response. */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	FString jsonString;

	FLovenseGetAdaptersResponseData() {
		this->code = 0;
		this->message = TEXT("");
		this->adapters = TArray<FLovenseAdapterDescription>();
		this->jsonString = TEXT("");
	}
};


/**
 * @brief Container holding (mostly) raw HTTP request json data from ILovenseAdapter::GetToys() response.
 */
USTRUCT(BlueprintType)
struct LOVENSEINTEGRATION_API FLovenseGetToysResponseData {
	GENERATED_BODY()

	/** @brief The response error type. Will be either "ok" or "error". */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	FString type;

	/** @brief The response error code. 200 = success. */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	int32 code;

	/** @brief Parsed toy descriptions from ILovenseAdapter::GetToys() response. */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	TArray<FLovenseToyDescription> toys;

	/** @brief The raw json object string from ILovenseAdapter::GetToys() response. */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense")
	FString jsonString;

	FLovenseGetToysResponseData() {
		this->type = TEXT("");
		this->code = 0;
		this->toys = TArray<FLovenseToyDescription>();
		this->jsonString = TEXT("");
	}
};


/**
 * @brief Structure holding all necessary information for a pattern command.
 */
USTRUCT(BlueprintType)
struct LOVENSEINTEGRATION_API FLovensePattern {
	GENERATED_BODY()

	/** @brief Whether the pattern will make the toy vibrate.  */
	UPROPERTY(BlueprintReadWrite, Category = "Lovense")
	bool bVibrate;

	/** @brief Whether the pattern will make the toy vibrate1.  */
	UPROPERTY(BlueprintReadWrite, Category = "Lovense")
	bool bVibrate1;

	/** @brief Whether the pattern will make the toy vibrate2.  */
	UPROPERTY(BlueprintReadWrite, Category = "Lovense")
	bool bVibrate2;

	/** @brief Whether the pattern will make the toy vibrate3.  */
	UPROPERTY(BlueprintReadWrite, Category = "Lovense")
	bool bVibrate3;

	/** @brief Whether the pattern will make the toy rotate.  */
	UPROPERTY(BlueprintReadWrite, Category = "Lovense")
	bool bRotate;

	/** @brief Whether the pattern will make the toy pump.  */
	UPROPERTY(BlueprintReadWrite, Category = "Lovense")
	bool bPump;

	/** @brief Whether the pattern will make the toy thrust.  */
	UPROPERTY(BlueprintReadWrite, Category = "Lovense")
	bool bThrust;

	/** @brief Whether the pattern will make the toy suck.  */
	UPROPERTY(BlueprintReadWrite, Category = "Lovense")
	bool bSuck;

	/** @brief Whether the pattern will make the toy finger.  */
	UPROPERTY(BlueprintReadWrite, Category = "Lovense")
	bool bFinger;

	/** @brief Whether the pattern will make the toy depth.  */
	UPROPERTY(BlueprintReadWrite, Category = "Lovense")
	bool bDepth;

	/** @brief The interval in milliseconds the pattern will be played at. Minimum interval is 100. */
	UPROPERTY(BlueprintReadWrite, Category = "Lovense")
	int32 interval;

	/** @brief Array of toy speed values (0-20) that constitutes the pattern. Maximum number of values is 50. */
	UPROPERTY(BlueprintReadWrite, Category = "Lovense")
	TArray<int32> pattern;

	/** @brief The time in seconds the pattern will play for. If 0, the pattern will play indefinitely, otherwise should be >=1. */
	UPROPERTY(BlueprintReadWrite, Category = "Lovense")
	float time;

	/** @brief Parses the pattern speed value array into a string for sending the command. */
	FString ParsePattern();

	FLovensePattern() {
		this->bVibrate = true;
		this->bVibrate1 = false;
		this->bVibrate2 = false;
		this->bVibrate3 = false;
		this->bRotate = true;
		this->bPump = true;
		this->bThrust = true;
		this->bSuck = true;
		this->bFinger = true;
		this->bDepth = true;
		this->interval = 100;
		this->pattern = TArray<int32>();
		this->time = 1;
	}
};


/**
 * @brief These timers define the minimum update frequencies for the respective commands.
 * \n There's a global set of these used when commands are broadcasted and each toy has their own set of these used when commands are sent to a specific toy.
 * \n Commands cannot be sent while their respective delay timer is active.
 * \n This is necessary as to not overwhelm the toys with commands.
 */
struct FLovenseCommandDelayTimers {
	FTimerHandle commandDelayTimerHandle_Vibrate = FTimerHandle();
	FTimerHandle commandDelayTimerHandle_Vibrate1 = FTimerHandle();
	FTimerHandle commandDelayTimerHandle_Vibrate2 = FTimerHandle();
	FTimerHandle commandDelayTimerHandle_VibRotateAir = FTimerHandle();
	FTimerHandle commandDelayTimerHandle_Rotate = FTimerHandle();
	FTimerHandle commandDelayTimerHandle_Air = FTimerHandle();
	FTimerHandle commandDelayTimerHandle_Thrust = FTimerHandle();
	FTimerHandle commandDelayTimerHandle_Suck = FTimerHandle();
	FTimerHandle commandDelayTimerHandle_Finger = FTimerHandle();
	FTimerHandle commandDelayTimerHandle_Preset = FTimerHandle();
	FTimerHandle commandDelayTimerHandle_All = FTimerHandle();
	FTimerHandle commandDelayTimerHandle_Pattern = FTimerHandle();
	float commandDelay_Vibrate = 0.2f;
	float commandDelay_Vibrate1 = 0.2f;
	float commandDelay_Vibrate2 = 0.2f;
	float commandDelay_VibRotateAir = 0.2f;
	float commandDelay_Rotate = 1.0f;
	float commandDelay_Air = 1.0f;
	float commandDelay_Thrust = 0.2f;
	float commandDelay_Suck = 0.2f;
	float commandDelay_Finger = 0.2f;
	float commandDelay_Preset = 1.0f;
	float commandDelay_All = 0.2f;
	float commandDelay_Pattern = 0.1f;
};


/**
 * @brief Callback delegate used in ILovenseAdapter::TryGetAdapterData().
 * \n Executed once "https://api.lovense-api.com/api/lan/v2/app" response has been received and parsed.
 * @param responseData (FLovenseGetAdaptersResponseData) The parsed response data. Will be default initialized if unsuccessful.
 */
DECLARE_DELEGATE_OneParam(FOnLovenseGetAdaptersResponse, FLovenseGetAdaptersResponseData);
/**
 * @brief Callback delegate used in ILovenseAdapter::GetToys().
 * \n Executed once GetToys response from the respective Lovense app has been received and parsed.
 * @param responseData (FLovenseGetToysResponseData) The parsed response data. Will be default initialized or only partially filled if unsuccessful.
 * @param toyStrongObjects (const TArray<TStrongObjectPtr<ULovenseToy>>&) The toy objects that were created. Will be empty if unsuccessful.
 */
DECLARE_DELEGATE_TwoParams(FOnLovenseGetToysResponse, FLovenseGetToysResponseData, const TArray<TStrongObjectPtr<class ULovenseToy>>&);
/**
 * @brief Blueprint exposed callback delegate used in ULovenseFunctionLibrary::SendCommand_Battery().
 * \n Executed once the battery status has been received.
 * @param toy (ULovenseToy*) The toy this command was called with.
 * @param responseValue (int32) Value indicating the battery level. Value range is -1-100, -1 meaning the battery status could not be fetched.
 */
DECLARE_DYNAMIC_DELEGATE_TwoParams(FOnLovenseResponseDynamic, class ULovenseToy*, toy, int32, responseValue);

/**
 * @brief Callback delegate used in FLovenseManager::SendCommand_Battery().
 * \n Executed once the battery status has been received.
 * @param responseValue (int32) Value indicating the battery level. Value range is -1-100, -1 meaning the battery status could not be fetched.
 */
DECLARE_DELEGATE_OneParam(FOnLovenseResponse, int32);

DECLARE_DYNAMIC_DELEGATE_OneParam(FOnGetSyncTime, int32, offsetTime);

DECLARE_DYNAMIC_DELEGATE_OneParam(FOnEventCode, int32, code);

DECLARE_DYNAMIC_DELEGATE_OneParam(FOnEveryShakeEvent, FString,toyId);

DECLARE_DYNAMIC_DELEGATE_OneParam(FOnGetLovenseEventToys, const TArray<UELovenseEventsToy*>&, toys);

DECLARE_DYNAMIC_DELEGATE_TwoParams(FOnLovenseConnectStatusEvent, FString, id, bool, isConnected);

DECLARE_DYNAMIC_DELEGATE_TwoParams(FOnLovenseBatteryEvent, FString, id, int32, battery);

DECLARE_DYNAMIC_DELEGATE_FourParams(FOnFunctionsEvent, FString, id, ELovenseEventType, type, int32, value, int32, index);

DECLARE_DYNAMIC_DELEGATE_ThreeParams(FOnButtonEvent, FString, id, ELovenseButtonEventType, type, int32, index);

DECLARE_DYNAMIC_DELEGATE_FourParams(FOnMotionChangedEvent, FString, id, bool, inOrOut, int32, position,int32, speed);





