#pragma once

#include "slot.h"
#include "chain.h"
#include "renderer.h"
#include <vector>

#if defined(TRACE_VIDEO_RENDERER) || defined(USE_ONE_VIDEO_TRACE)
extern BitTrace Video_Renderer;
#endif

#if defined(TRACE_VIDEO_RENDERER)
#define SET_VIDEO_RENDERER() Video_Renderer.Set()
#define CLEAR_VIDEO_RENDERER() Video_Renderer.Clear()
#else
#define SET_VIDEO_RENDERER()
#define CLEAR_VIDEO_RENDERER()
#endif

#if defined(TRACE_VIDEO_BECOME_INTERESTING)
#if defined(USE_ONE_VIDEO_TRACE)
#define SET_VIDEO_BECOME_INTERESTING() Video_Renderer.Set()
#define CLEAR_VIDEO_BECOME_INTERESTING() Video_Renderer.Clear()
#else
extern BitTrace Video_Become_Interesting;
#define SET_VIDEO_BECOME_INTERESTING() Video_Become_Interesting.Set()
#define CLEAR_VIDEO_BECOME_INTERESTING()\
Video_Become_Interesting.Clear()
#endif
#else
#define SET_VIDEO_BECOME_INTERESTING()
#define CLEAR_VIDEO_BECOME_INTERESTING()
#endif

#if defined(TRACE_VIDEO_BECOME_UNINTERESTING)
#if defined(USE_ONE_VIDEO_TRACE)
#define SET_VIDEO_BECOME_UNINTERESTING() Video_Renderer.Set()
#define CLEAR_VIDEO_BECOME_UNINTERESTING() Video_Renderer.Clear()
#else
extern BitTrace Video_Become_Uninteresting;
#define SET_VIDEO_BECOME_UNINTERESTING()\
Video_Become_Uninteresting.Set()
#define CLEAR_VIDEO_BECOME_UNINTERESTING()\
Video_Become_Uninteresting.Clear()
#endif
#else
#define SET_VIDEO_BECOME_UNINTERESTING()
#define CLEAR_VIDEO_BECOME_UNINTERESTING()
#endif

class VideoRenderer : public Renderer
{
public:
	VideoRenderer(RendererRate calibration_rate, RendererComplexity calibration_complexity, RendererPriority calibration_priority, InterestType interest_type, InterestDepth depth_calibration);
	~VideoRenderer();

	Logical TestInstance() const;

   virtual void ConsolidateStaticObjects() = 0;
   virtual std::vector<MONITORINFO> MonitorsCreateAll(int &count) = 0;

	//
	//--------------------------------------------------------------------
	// NotifyOfNewInterestingEntity
	//
	// This method tells the renderer that a new entity will be in it's
	// interest list the next time the Execute method is called.
	//--------------------------------------------------------------------
	//
	void NotifyOfNewInterestingEntity(Entity *interesting_entity);

	void NotifyOfBecomingUninterestingEntity(Entity *uninteresting_entity);

	virtual int *GetSecondaryIndex() = 0;
	virtual int *GetAux1Index() = 0;
	virtual int *GetAux2Index() = 0;

private:
	void LoadMissionImplementation(Mission *mission);
	void ShutdownImplementation();
	void SuspendImplementation();
	void ResumeImplementation();
	void ExecuteImplementation(RendererComplexity complexity_update, RendererOrigin::InterestingEntityIterator *iterator);

protected:

	enum ViewFrom
	{
		outsideEntity,		// The external view of an entity will be displayed
		insideEntity,		// The internal view of the entity will be displayed
		collisionEntity		// The collision solids of the entity will be displayed
	};

	//
	//--------------------------------------------------------------------
	// MakeEntityRenderables
	//
	// This method is called to create the renderables for a given entity
	// it must be provided by the hardware specific renderer.
	//--------------------------------------------------------------------
	//
	virtual void MakeEntityRenderables(Entity*, ResourceDescription*, ViewFrom);

	Logical Disconnected_Eye;	// If this is true, we will construct an outside
								// version of the viewpoint entity.  This is so
								// higher level renderers can fix the eye in one
						        // spot and watch the viewpoint entity drive around.
};