#pragma once

#include "..\munga\graph2d.h"
#include "..\munga\time.h"
#include <D3DX9.h>
#include <D3DX9math.h>


class L4graphicsPort;

//########################################################################
//######################### Video16BitBuffered ###########################
//########################################################################
//
// X/Y values passed to these routines are assumed to be in
// the VIDEO DISPLAY COORDINATE SYSTEM, with (0,0) at the top left.
//
class Video16BitBuffered :
	public GraphicsDisplay
{
public:
	Video16BitBuffered(int x, int y);

	~Video16BitBuffered();

	Logical
		TestInstance() const;

	void
		ShowInstance(char *indent);

	void
		DrawPoint(
			int color,
			int bitmask,
			Enumeration operation,
			int x, int y
		);

	void
		DrawLine(
			int color,
			int bitmask,
			Enumeration operation,
			int x1, int y1,
			int x2, int y2,
			Logical include_last_pixel
		);

	void
		DrawFilledRectangle(
			int color,
        int bitmask,
			Enumeration operation,
			int x1, int y1,
			int x2, int y2
		);

	void
		DrawText(
			int color,
			int bitmask,
			Enumeration operation,
			Logical opaque,
			int rotation,
			Enumeration fontNumber,
			Logical vertical,
			GraphicsDisplay::Justification justification,
			Rectangle2D	*clippingRectanglePtr,
			char *stringPointer
		);

	void
		DrawBitMap(
			int color,
			int bitmask,
			Enumeration operation,
			int rotation,
			int x, int y,
			BitMap *bitmap,
			int sx1, int sy1, int sx2, int sy2	// these are SOURCE coordinates
		);

	void
		DrawBitMapOpaque(
			int color,
			int background,
			int bitmask,
			Enumeration operation,
			int rotation,
			int x, int y,
			BitMap *bitmap,
			int sx1, int sy1, int sx2, int sy2	// these are SOURCE coordinates
		);

	void
		DrawPixelMap8(
     	int *translation_table,
			int bitmask,
			Enumeration operation,
			Logical opaque,
			int rotation,
			int x, int y,
			PixelMap8	*pixelmap,
			int sx1, int sy1, int sx2, int sy2	// these are SOURCE coordinates
		);

	void
		DrawPixelMap8SingleColor(
			int color,
			int bitmask,
			Enumeration operation,
			int rotation,
			int x, int y,
			PixelMap8	*pixelmap,
			int sx1, int sy1, int sx2, int sy2	// these are SOURCE coordinates
		);

protected:
	void
		MarkChangedLines(int screenTop, int screenBottom);

	void
		buildDestPointer(
			int x, int y,
			Word **pixelPointer,
			LWord **changed_bit_pointer,
			LWord *changed_bit
		);

	Logical
		valid;
	int
		width,
		changedBitWidth,
		height,
		maximumX,
		maximumY;

	PixelMap16
		pixelBuffer;
	Byte
		*changedLine;
	LWord
		*changedBit;
};


//########################################################################
//################################ SVGA16 ################################
//########################################################################
struct SVGA16Palette
{
	Word
		hardwarePort;
	Logical
		modified;
	Palette8
		paletteData;
	Scalar
		flashAccumulator,
		flashRate;

	enum PaletteID
	{
		maskStates=4
	};
	unsigned char
		mask[maskStates];
	int
  	previousMaskState;
};


class SVGA16 :
	public Video16BitBuffered
{
friend class L4GraphicsPort;		// for palette access

public:
	enum PaletteID {
		NativePalette=0,
		SecondaryPalette,
		AuxiliaryPalette1,
		AuxiliaryPalette2,
		PaletteCount
	};

	SVGA16(
		int mode,
		int width,
		int height,
		int page_size,
		int mem_granularity,
		int bytes_per_line,
		int page_function_pointer,
		int special_interface,
      bool windowed,
	  int *secondaryIndex,
	  int *aux1Index, 
	  int *aux2Index
	);

	~SVGA16();

	Logical
		TestInstance() const;

	void
		ShowInstance(char *indent);

	Logical
		Update(Logical forceall);
	void
		Refresh();
	void
		UpdatePalette();

	void
		FadeToPalettes(Scalar fade_time);
	void
		FadeToWhite(Scalar fade_time);
	void
		FlashPalette(
			int palette_number,
			Scalar rate,
			unsigned char *stateList
		);
	void
		UnflashPalette(int palette_number);

	void
		FunkyVideo(Logical on_off);

protected:

   void BuildWindows(unsigned int width, unsigned int height, bool windowed, int *secondaryIndex, int *aux1Gauge, int *aux2Gauge);


	void
		ResetUpdatePosition();

	int
		pageSize,
		pageDelta,
		widthInBytes,
		pageFcnPtr,
		specialInterface;

	int
		currentPageNumber,
     nextPageNumber,
		lineNumber;
	long
		destOffset;
	Byte
		*changedLinePointer;
	Word
		*sourcePointer;
	LWord
		*changedBitPointer;

	enum PaletteFadeState
	{
		staticPalette,
		fadeToWhite,
		whitePalette,
		fadeToColor
	};

	PaletteFadeState
		paletteFadeState;
	Scalar
		fadeAlpha,
		fadeUnitsPerSecond;
	Time
  	previousFadeTime;

	// This array is closely linked to the PaletteID enumeration, above
	SVGA16Palette
		palette[PaletteCount];

private:
	int NUMGAUGEWINDOWS;
   HWND *gaugeWindows;
   LPDIRECT3DDEVICE9 *mDevice;
   D3DPRESENT_PARAMETERS *mPresentParams;
   LPDIRECT3DVERTEXBUFFER9 *mVertBuffers;
   LPDIRECT3DTEXTURE9 *mSurfaces;
   DWORD *mLockFlags;
   RECT *mSurfaceRects;

   int mDisplayToUpdate;
};

//########################################################################
//########################## L4GraphicsPort ##############################
//########################################################################
//
// X/Y values passed to these routines are assumed to be in
// the GRAPHICS COORDINATE SYSTEM, with (0,0) at the bottom left.
//
class L4GraphicsPort :
	public GraphicsPort
{
public:
	enum ChannelEnableID {
		RedChannel,
		GreenChannel,
		BlueChannel,
		AllChannels,

		DirectColor,
		BlankColor,

		RedChannelTransparentZero=0x80,
		GreenChannelTransparentZero,
		BlueChannelTransparentZero,
		AllChannelsTransparentZero
	};

	L4GraphicsPort(
		Video16BitBuffered *graphics_display,
		const char *name,
		int rotation,
		int bit_mask,
		SVGA16::PaletteID palette_ID,
		L4GraphicsPort::ChannelEnableID channel_enable
	);

	~L4GraphicsPort();

	Logical
		TestInstance() const;

	void
		ShowInstance(char *indent);

	void
		SetSecondaryPalette(
			Palette8 *source_palette
		);

	void
		SetAuxiliaryPalette();

	void
		SetColor(
			PaletteTriplet *source_color,
			int color_index
		);

	void
		DrawPoint(
			int color,
			Enumeration operation,
			int x, int y
		);

	void
		DrawLine(
			int color,
			Enumeration operation,
			int x1, int y1,
			int x2, int y2,
			Logical include_last_pixel
		);

	void
		DrawFilledRectangle(
			int color,
			Enumeration operation,
			int x1, int y1,
			int x2, int y2
		);

	void
		DrawText(
			int color,
			Enumeration operation,
			Logical opaque,
			int rotation,
			Enumeration fontNumber,
			Logical vertical,
			GraphicsDisplay::Justification justification,
			Rectangle2D	*clippingRectanglePtr,
			char *stringPointer
		);

	void
		DrawBitMap(
			int color,
			Enumeration operation,
			int rotation,
			int x, int y,
			BitMap *bitmap,
			int sx1, int sy1, int sx2, int sy2	// these are SOURCE coordinates
		);

	void
		DrawBitMapOpaque(
			int color,
        int background,
			Enumeration operation,
			int rotation,
			int x, int y,
			BitMap *bitmap,
			int sx1, int sy1, int sx2, int sy2	// these are SOURCE coordinates
		);

	void
		DrawPixelMap8(
			Enumeration operation,
			Logical opaque,
			int rotation,
			int x, int y,
			PixelMap8	*pixelmap,
			int sx1, int sy1, int sx2, int sy2	// these are SOURCE coordinates
		);

	void
		DrawPixelMap8SingleColor(
     	int color,
			Enumeration operation,
			int rotation,
			int x, int y,
			PixelMap8	*pixelmap,
			int sx1, int sy1, int sx2, int sy2	// these are SOURCE coordinates
		);

	void
		SetPaletteID(SVGA16::PaletteID palette_ID)
			{
				Check(this);
				paletteID = palette_ID;
			}

	void
		SetEnableID(L4GraphicsPort::ChannelEnableID channel_enable)
			{
				Check(this);
				channelEnable = channel_enable;
			}

	int
		GetBitMask()
			{
				Check(this);
				return bitMask;
			}
	SVGA16::PaletteID
  	paletteID;

protected:
	void
		convertPortPair(
			int *xp,
			int *yp,
			int x,
			int y
		);

	void
		BuildDirectTranslation(
			Palette8 *source_palette
		);

	void
		BuildSecondaryPalette(
			Palette8 *source_palette
		);

	void
		BuildAuxiliaryPalette();

	void
		BuildSecondaryTranslation();

	void
		BuildAuxiliaryTranslation();

	void
		BlankPalette();

	void
		BuildSecondaryColor(
			PaletteTriplet *source_triplet,
			int color_number
		);
	//------------------------------------------------------------
	// Protected data
	//------------------------------------------------------------
	int
		translationTable[256];
	unsigned char
		myColor[256];

	int
		baseRotation,
		bitMask,
		numberOfBits,
		maximumX,
		maximumY;


	L4GraphicsPort::ChannelEnableID
		channelEnable;
};
