#ifndef BARNES_HUT_TREE_THREADED_HPP
#define BARNES_HUT_TREE_THREADED_HPP

#include <vector>
#include "BarnesHutTree.hpp"

namespace nbody {
	using namespace std;

	class BarnesHutTreeThreaded;

	typedef struct NodesToProcessStruct {
		pthread_mutex_t mutex;
		vector<Node*> toProcess;
		vector<pthread_t> processing;
		BarnesHutTreeThreaded* tree;
		pthread_barrier_t* barrier;
		int iterations;
		vector<Body>* bodies;
		vector<pthread_t>* threads;
	} NodesToProcess;

	class BarnesHutTreeThreaded : public BarnesHutTree {
		friend class PthreadSimulation;
	protected:
		NodesToProcess nodesToProcess;

		static void splitSubtree(Node* root);
		static void* build(void* data);
		static void* computeMove(void* data);
		static void updateNode(Node* current);
		static void addNodeToProcess(Node* node, NodesToProcess* store);
		static Node* getNodeToProcess(NodesToProcess* store);
		static void checkNodeProcessingFinished(NodesToProcess* store);
		static bool hasNodeProcessingFinished(NodesToProcess* store);
		virtual void clearNodesToProcess();
	public:
		BarnesHutTreeThreaded(int parallelId);
		virtual ~BarnesHutTreeThreaded();
		virtual void build(vector<Body> bodies, Box domain);
		virtual void computeMove();
	};
}

#endif
