// Project Lab - NHTV Igad

#pragma once

#include "GUI/Menu/MenuItemBase.h"
#include "SubMenu.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FMenuChange);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FSubMenuItemSelected, UMenuItemBase*, item);

UCLASS()
class UNREALPROJECT_API UPanelUserWidget : public UUserWidget
{
	GENERATED_BODY()
public:
};

UCLASS()
class UNREALPROJECT_API USubMenu : public UMenuItemBase
{
	GENERATED_BODY()
public:
	USubMenu(const FObjectInitializer& init);
	virtual void NativeConstruct() override;
	virtual void NativeDestruct() override;
	virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override;

	UFUNCTION(BlueprintCallable, Category = "SubMenu")
	virtual void RescanItems();

	UFUNCTION(BlueprintCallable, Category = "SubMenu")
	void CloseSubMenu();

	virtual void OnEnter(class UMenuScreenBase* screen);
	virtual void OnLeave();

	UFUNCTION(BlueprintCallable, Category = "SubMenu")
	bool HasFocus() const;

	virtual void OnSuspend(USubMenu* newSubMenu, bool loseFocus);
	virtual void OnRestore(USubMenu* removedMenu);

	// Callback that gets called whenever the button hits should update when showing this menu
	UFUNCTION(BlueprintImplementableEvent, Category = "SubMenu")
	void SetButtonHints();

	UFUNCTION(BlueprintCallable, Category = "SubMenu")
	class UButtonHintBar* GetButtonHintBar() const;

	UFUNCTION(BlueprintCallable, Category = "SubMenu")
	class UCharacterSettings* GetCharacterSettings() const;
	UFUNCTION(BlueprintCallable, Category = "SubMenu")
	class UPrefs* GetPrefs() const;
	UFUNCTION(BlueprintCallable, Category = "SubMenu")
	class UDefaultGameInstance* GetGameInstance() const;

	virtual void NativeOnMenuAction(EMenuActionBinding binding) override;
	virtual void NativeOnSelectionConfirmed(UMenuItemBase* item);

	UFUNCTION(BlueprintCallable, Category="SubMenu")
	UMenuItemBase* GetItem(int32 itemIndex) const;
	UFUNCTION(BlueprintCallable, Category = "SubMenu")
	int32 GetNumItems() const;
	UFUNCTION(BlueprintCallable, Category = "SubMenu")
	int32 GetSelectedItem() const;

	UFUNCTION(BlueprintCallable, Category = "SubMenu")
	void SelectNewItemByIndex(int32 idx);
	UFUNCTION(BlueprintCallable, Category = "SubMenu")
	void SelectNewItem(UMenuItemBase* item);
	void SelectNewItemByIndex(int32 idx, bool controller);

	UFUNCTION(BlueprintCallable, Category = "SubMenu")
	int32 GetItemIndex(UMenuItemBase* item);

	UFUNCTION(BlueprintCallable, Category = "SubMenu")
	UMenuScreenBase* GetScreen() const;

	// Called when an item is selected
	UPROPERTY(BlueprintAssignable, Category="SubMenu")
	FSubMenuItemSelected onItemSelected;
	// Called when a button is pressed
	UPROPERTY(BlueprintAssignable, Category="SubMenu")
	FSubMenuItemSelected onItemSelectionConfirmed;

	// Called when the back button is pressed
	UPROPERTY(BlueprintAssignable, Category = "SubMenu")
	FMenuChange onBack;

	UPROPERTY(BlueprintAssignable, Category = "SubMenu")
	FMenuChange onClosed;
	UPROPERTY(BlueprintAssignable, Category = "SubMenu")
	FMenuChange onOpened;

	// Called when another menu is opened on top of this menu
	UPROPERTY(BlueprintAssignable, Category = "SubMenu")
	FMenuChange onSuspend;
	// Called when this menu is displayed again after a menu was closed on top of this
	UPROPERTY(BlueprintAssignable, Category = "SubMenu")
	FMenuChange onRestore;
		
	// The panel widget that contains all the buttons selectable in this menu
	UPROPERTY(BlueprintReadWrite, Category="SubMenu")
	UPanelWidget* container;

protected:
	void m_ScanContainer(UWidget* widget, int32 depth = 0);
	// Set the allowance of mouse focus & presses of the buttons in this menu
	void m_SetFocus(bool focus);

	// The list of selectable items in the menu
	UPROPERTY()
	TArray<UMenuItemBase*> m_items;

private:
	friend class UMenuItemBase;
	int32 m_selectedItem;

	// Horizontal or vertical input handling
	int m_layoutDirection;

	UPROPERTY()
	class UMenuScreenBase* m_screen;

	// True if this is the topmost screen and if the buttons in this screen are allowed to be pressed.
	bool m_focus;
};
