#pragma once

#include "Proxies.hpp"
#include "BinSort.hpp"

namespace Proxies {

	class SortInterestZonesProcess:
		public Process
	{
	public:
		SortInterestZonesProcess(
			Stuff::NotationFile *config_file,
			const char* set_path,
			const Stuff::DynamicArrayOf<Stuff::ExtentBox> &zone_array,
			BinSortProcess *bin_process,
			FindErrorsProcess *find_errors
		);

		virtual void
			SplitCallback(Proxies::GenericProxy *proxy);
		virtual void
			CreateCallback(Proxies::GenericProxy *proxy);
		virtual FlattenHierarchyProcess*
			MakeFlattenHierarchyProcess(
				Stuff::NotationFile *config_file,
				GroupProxy *parent_group
			);

		const char
			*setDirectory;
		const Stuff::DynamicArrayOf<Stuff::ExtentBox>
			&zoneArray;
		unsigned
			zoneCounter;
		Stuff::NotationFile
			*setContents,
			*configFile;
		Stuff::Scalar
			trimmingTolerance;
		BinSortProcess
			*sortProcess;
		FindErrorsProcess
			*errorProcess;
	};

	//
	//#########################################################################
	//########################    InterestBSP    ##############################
	//#########################################################################
	//
	class InterestBSP
		#if defined(_ARMOR)
			: public Stuff::Signature
		#endif
	{
	public:
		InterestBSP():
			insideNode(NULL),
			outsideNode(NULL)
				{}
		~InterestBSP();

		Stuff::Plane
			dividingPlane;
		InterestBSP
			*insideNode,
			*outsideNode;
		unsigned
			zoneIndex;

		enum {
			ContainsAll,
			Splits,
			ContainsNone
		};

		static InterestBSP*
			CreateBSPTree(SortInterestZonesProcess *process);

		void
			SplitScene(
				SortInterestZonesProcess *process,
				SceneProxy *scene
			);

		void
			TestInstance() const
				{}

	protected:
		static InterestBSP*
			MakeBSPNode(
				SortInterestZonesProcess *process,
				const Stuff::DynamicArrayOf<int> &scoreboard,
				const Stuff::DynamicArrayOf<Stuff::Plane> &planes,
				Stuff::DynamicArrayOf<unsigned> &index,
				unsigned zone_count
			);

		bool
			SplitGroup(
				SortInterestZonesProcess *process,
				GroupProxy *group
			);

		bool
			SplitMesh(
				SortInterestZonesProcess *process,
				PolygonMeshProxy *mesh,
				GroupProxy *inside_set,
				GroupProxy *outside_set
			);

		bool
			CreateInterestZone(
				SortInterestZonesProcess *process,
				GenericProxy *proxy
			);

		void
			OptimizeBasket(
				SortInterestZonesProcess *process,
				GroupProxy *basket
			);
	};

}
