#ifndef _MIND_H
#define _MIND_H

#include <config.h>
#include <thread>
#include <functional>
#include <memory>
#include <unordered_map>
#include <string>
#include <callback.h>

#include <component.h>
#include <componentThread.h>
#include <director/director.h>
#include <simulator/simulator.h>
#include <body/body.h>

namespace smo {

class Mind : public std::enable_shared_from_this<Mind>
{
public:
	Mind(void);
	~Mind(void) = default;

	typedef std::function<void(bool)> mindLifetimeMgmtOpCbFn;
	void initializeReq(Callback<mindLifetimeMgmtOpCbFn> callback);
	void finalizeReq(Callback<mindLifetimeMgmtOpCbFn> callback);

	// ComponentThread access methods
	std::shared_ptr<MindThread> getComponentThread(
		ComponentThread::ThreadId id) const;
	std::shared_ptr<MindThread> getComponentThread(
		const std::string& name) const;
	// Get all this Mind's component threads.
	std::vector<std::shared_ptr<MindThread>> getMindThreads() const;

	// Thread management methods (moved from ComponentThread)
	typedef std::function<void()> mindThreadLifetimeMgmtOpCbFn;
	void joltAllMindThreadsReq(Callback<mindThreadLifetimeMgmtOpCbFn> callback);
	void startAllMindThreadsReq(
		Callback<mindThreadLifetimeMgmtOpCbFn> callback);
	void pauseAllMindThreadsReq(
		Callback<mindThreadLifetimeMgmtOpCbFn> callback);
	void resumeAllMindThreadsReq(
		Callback<mindThreadLifetimeMgmtOpCbFn> callback);
	void exitAllMindThreadsReq(Callback<mindThreadLifetimeMgmtOpCbFn> callback);

	// CPU distribution method
	void distributeAndPinThreadsAcrossCpus();

private:
	// Collection of ComponentThread instances (excluding marionette)
	std::vector<std::shared_ptr<MindThread>> componentThreads;

public:
	director::Director		director;
	simulator::Simulator	canvas;
	MindComponent			subconscious;
	body::Body				body;
	MindComponent			world;

private:
	friend class body::Body;
	/**
	 * Indicates whether all mind threads have been JOLTed at least once.
	 *
	 * JOLTing serves two critical purposes:
	 *
	 * 1. **Global Constructor Sequencing**: Since pthreads begin executing while
	 *    global constructors are still being executed, globally defined pthreads
	 *    cannot depend on global objects having been constructed. JOLTing is done
	 *    by the CRT's main thread within main(), which provides a sequencing
	 *    guarantee that global constructors have been called.
	 *
	 * 2. **shared_from_this Safety**: shared_from_this() requires a prior
	 *    shared_ptr handle to be established. The global list of
	 *    shared_ptr<ComponentThread> guarantees that at least one shared_ptr to
	 *    each ComponentThread has been initialized before JOLTing occurs.
	 *
	 * This flag ensures that JOLTing happens exactly once and provides
	 * a synchronization point for the entire system initialization.
	 */
	bool threadsHaveBeenJolted = false,
		bodyComponentInitialized = false;

private:
	class MindLifetimeMgmtOp;
	class MindThreadLifetimeMgmtOp;
};

namespace mind {
// Global Mind instance will be defined in marionette.cpp
extern std::shared_ptr<Mind> globalMind;
} // namespace mind

} // namespace smo

#endif
