#ifndef _MIND_H
#define _MIND_H

#include <config.h>
#include <memory>
#include <string>

#include <spinscale/puppetApplication.h>
#include <spinscale/component.h>
#include <componentThread.h>
#include <mindThread.h>
#include <mindComponent.h>
#include <marionette/marionetteThread.h>
#include <director/director.h>
#include <simulator/simulator.h>
#include <body/body.h>

namespace smo {

class Mind
:	public sscl::PuppetApplication
{
public:
	Mind(void);
	~Mind(void) = default;

	mrntt::MrnttViralNonPostingInvokerT<void> initializeCReq();
	mrntt::MrnttViralNonPostingInvokerT<void> finalizeCReq();

	// ComponentThread access methods
	std::shared_ptr<MindThread> getComponentThread(sscl::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;

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

private:
	friend class body::Body;
	bool bodyComponentInitialized = false;
};

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

} // namespace smo

#endif
