// (CVN) - Candy Valley Network GmbH

#pragma once

#include <CoreMinimal.h>

// EXTERNAL INCLUDES

// INTERNAL INCLUDES
#include "LovenseTypes.h"

#include "LovenseToy.generated.h"


/**
 * @brief UObject representing a Lovense Toy.
 */
UCLASS(BlueprintType)
class LOVENSEINTEGRATION_API ULovenseToy : public UObject {
	GENERATED_BODY()

	friend class ILovenseAdapter;
	friend class FLovenseManager;

public:
	UFUNCTION(BlueprintPure, Category = "Lovense|Toy")
	FORCEINLINE FString GetTypeName() { return this->toyDescription.name; }
	/**
	 * @brief Compiles the full toy name in this format: "[ToyName] [ToyVersion] ([ToyNickname]) e.g. "Max 2 (Funny Name)".
	 * \n If the toy does not have a version or the version is 1, it will be omitted. E.g. "Nora (Funny Name)".
	 * \n If the user has not set a nickname, it will be omitted. E.g. "Diamo".
	 * \n This follows the naming convention of the Lovense Apps.
	 */
	UFUNCTION(BlueprintPure, Category = "Lovense|Toy")
	FString GetFullToyName();

	/** @brief Compiles the app type and platform of the adapter this toy is associated with in this format: "[apptype] [platform]" e.g. "remote android" or "connect pc" */
	UFUNCTION(BlueprintPure, Category = "Lovense|Toy")
	FString GetAssociatedAdapterPlatformName();

	/** @brief Whether this toy's connection to the Lovense App is active. */
	UFUNCTION(BlueprintPure, Category = "Lovense|Toy")
	FORCEINLINE bool IsConnected() { return !!this->toyDescription.status; }

	/**
	 * @brief Current battery status of the toy. Value is percentage charged, range is 0-100%.
	 * \n If battery status is unknown, returned value will be -1.
	 */
	UFUNCTION(BlueprintPure, Category = "Lovense|Toy")
	FORCEINLINE int32 GetBatteryStatus() { return this->toyDescription.battery; }

	/** @brief Whether this toy is currently running a test command. A test command vibrates the toy at speed 10 for 1 second. */
	UFUNCTION(BlueprintPure, Category = "Lovense|Toy")
	bool IsRunningTestCommand();

	/**
	 * @brief Checks whether this is a valid UObject and has all required information for normal functionality.
	 * \n This should only ever be false if any cached toy objects were not updated during ULovenseEvents::onLovenseUpdatedToys.
	 * @note You should not need to check this in most cases as this will be checked internally when using this object.
	 */
	UFUNCTION(BlueprintPure, Category = "Lovense|Toy")
	bool IsValidToy();

public:
	ULovenseToy();

	/** @return Toy identifier string. */
	FORCEINLINE const FString& GetToyID() { return this->toyDescription.id; }

	/** @brief The toy description of this toy. Holds (mostly) raw ILovenseAdapter::GetToys() HTTP request json data for this adapter. */
	FORCEINLINE const FLovenseToyDescription& GetToyDescription() { return this->toyDescription; }
	/** @brief Called by the Lovense Adapters to set the toy description of this toy. Holds (mostly) raw GetToys() HTTP request json data for this adapter. */
	FORCEINLINE void SetToyDescription(const FLovenseToyDescription& description) { this->toyDescription = description; }

private:
	/** @brief The toy description of this toy. Holds (mostly) raw ILovenseAdapter::GetToys() HTTP request json data for this adapter. */
	UPROPERTY(BlueprintReadOnly, Category = "Lovense|Toy", Meta = (AllowPrivateAccess = "true"))
	FLovenseToyDescription toyDescription;

private:
	/** @brief The adapter this toy is associated with. */
	class ILovenseAdapter* lovenseAdapter;
	/** @brief Toy specific set of Command Delay Timers used when commands are executed on a specific toy. See FLovenseCommandDelayTimers for more information. */
	FLovenseCommandDelayTimers commandDelayTimers;
};
