#ifndef __PROPERTYBEHAVIOR__H__
#define __PROPERTYBEHAVIOR__H__

#include "BehaviorStates.h"
#include "State.h"

#include <optional>

namespace tinyxml2 {
	class XMLElement;
}

class AMFArrayValue;
class BehaviorMessageBase;
class ModelComponent;

struct UpdateResult {
	std::optional<BehaviorState> newState;
};

/**
 * Represents the Entity of a Property Behavior and holds data associated with the behavior
 */
class PropertyBehavior {
public:
	PropertyBehavior(bool _isTemplated = false);

	template <typename Msg>
	void HandleMsg(Msg& msg);

	// If the last edited state has no strips, this method will set the last edited state to the first state that has strips.
	void VerifyLastEditedState();
	void SendBehaviorListToClient(AMFArrayValue& args) const;
	void SendBehaviorBlocksToClient(AMFArrayValue& args) const;
	void CheckModifyState(BehaviorMessageBase& msg);

	[[nodiscard]] LWOOBJID GetBehaviorId() const noexcept { return m_BehaviorId; }
	void SetBehaviorId(LWOOBJID id) noexcept { m_BehaviorId = id; }

	bool GetIsLoot() const noexcept { return isLoot; }
	void SetIsLoot(const bool val) noexcept { isLoot = val; }

	const std::string& GetName() const noexcept { return m_Name; }

	void Serialize(tinyxml2::XMLElement& behavior) const;
	void Deserialize(const tinyxml2::XMLElement& behavior);

	void Update(float deltaTime, ModelComponent& modelComponent);
	void OnChatMessageReceived(const std::string& sMessage);
	void OnHit();

private:
	State& GetActiveState();
	// The current active behavior state. Behaviors can only be in ONE state at a time.
	BehaviorState m_ActiveState;

	// The states this behavior has.
	std::map<BehaviorState, State> m_States;

	// The name of this behavior.
	std::string m_Name = "New Behavior";

	// Whether this behavior is locked and cannot be edited.
	bool isLocked = false;

	// Whether this behavior is custom or pre-fab.
	bool isLoot = false;

	// Whether or not the behavior has been modified from its original state.
	bool isTemplated;

	// The last state that was edited. This is used so when the client re-opens the behavior editor, it will open to the last edited state.
	// If the last edited state has no strips, it will open to the first state that has strips.
	BehaviorState m_LastEditedState;

	// The behavior id for this behavior. This is expected to be fully unique, however an id of -1 means this behavior was just created
	// and needs to be assigned an id.
	LWOOBJID m_BehaviorId = -1;
};

#endif  //!__PROPERTYBEHAVIOR__H__
