#ifndef SWITCHCOMPONENT_H
#define SWITCHCOMPONENT_H

#include "RakNetTypes.h"
#include "Entity.h"
#include "GameMessages.h"
#include "EntityManager.h"
#include "QuickBuildComponent.h"
#include "BouncerComponent.h"
#include <algorithm>
#include "Component.h"
#include "eReplicaComponentType.h"

/**
 * A component for switches in game, including pet triggered switches.
 */
class SwitchComponent final : public Component {
public:
	static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SWITCH;

	SwitchComponent(Entity* parent, const int32_t componentID);
	~SwitchComponent() override;

	void Update(float deltaTime) override;
	void OnUse(Entity* originator) override;

	Entity* GetParentEntity() const;

	void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

	/**
	 * Sets whether the switch is on or off.
	 * @param active whether the switch is on or off.
	 */
	void SetActive(bool active);

	/**
	 * Returns whether the switch is on or off.
	 */
	bool GetActive() const;

	/**
	 * Sets the attached pet bouncer
	 * @param value the attached pet bouncer
	 */
	void SetPetBouncer(BouncerComponent* value);

	/**
	 * Returns the attached pet bouncer
	 */
	BouncerComponent* GetPetBouncer() const;

	/**
	 * Invoked when a entity enters the trigger area.
	 */
	void EntityEnter(Entity* entity);

	/**
	 * Invoked when a entity leaves the trigger area.
	 */
	void EntityLeave(Entity* entity);

	/**
	 * Returns the closest switch from a given position
	 * @param position the position to check
	 * @return the closest switch from a given position
	 */
	static SwitchComponent* GetClosestSwitch(NiPoint3 position);

	const std::vector<int32_t>& GetFactionsToRespondTo() const {
		return m_FactionsToRespondTo;
	}

private:
	/**
	 * A list of all pet switches.
	 */
	static std::vector<SwitchComponent*> petSwitches;

	/**
	 * Attached rebuild component.
	 */
	QuickBuildComponent* m_QuickBuild;

	/**
	 * If the switch is on or off.
	 */
	bool m_Active;

	/**
	 * The amount of entities in the trigger area.
	 */
	int m_EntitiesOnSwitch = 0;

	/**
	 * The switch reset time
	 */
	int m_ResetTime = INT_MAX;

	/**
	 * Timer for resetting the switch
	 */
	float m_Timer = 0.0f;

	/**
	 * Attached pet bouncer
	 */
	BouncerComponent* m_PetBouncer = nullptr;

	std::vector<int32_t> m_FactionsToRespondTo{};
};

#endif // SWITCHCOMPONENT_H
