#define MAX_SEGMENTS 128

#define LOW_SEGMENTS 4
#define MED_SEGMENTS 16
#define HIGH_SEGMENTS 64

#include "plugin.h"

IDirect3DDevice9* Device;
LPD3DXLINE Line;
D3DXVECTOR3 Vertices[MAX_SEGMENTS + 1];
int Segments;
int Rings;

void Init(IDirect3DDevice9* device);
void Quit(void);
void Render(PluginData* Data);

void Create();

Manifest MosaicPlugin = {
	PLUGIN_VER, 
	PLUGIN_NAME,
	PLUGIN_DESC,
	Init,        
	Quit,        
	Render,
	&Properties
};
 
void Init(IDirect3DDevice9* device) 
{
	Device = device;

	if (Device != NULL) 
	{
		D3DXCreateLine(Device, &Line);
		Line->SetAntialias(true);
		Line->SetWidth(1.0f);

		Rings = 400;

		Create();
	}
}

void Create()
{
	switch (Properties.Resolution)
	{
		case RES_SIMPLE:
			Segments = LOW_SEGMENTS;
			break;
		case RES_DETAILED:
			Segments = HIGH_SEGMENTS;
			break;
		default:
			Segments = MED_SEGMENTS;
			break;
	}

	for(int j = 0; j < Segments; j++)
	{
		float angle = D3DX_PI * 2 / Segments * j;
		Vertices[j] = D3DXVECTOR3(sin(angle), cos(angle), 0.0f);
	}

	Vertices[Segments] = Vertices[0];
}

void Quit() 
{
	if (Line != NULL)
	{
		Line->Release();
		Line = NULL;
	}
}

void Render(PluginData* Data)
{
	if (Device != NULL) 
	{
		switch (Properties.Resolution)
		{
			case RES_SIMPLE:
				if (Segments != LOW_SEGMENTS)
					Create();
				break;
			case RES_DETAILED:
				if (Segments != HIGH_SEGMENTS)
					Create();
				break;
			default:
				if (Segments != MED_SEGMENTS)
					Create();
				break;
		}

		D3DXMATRIX scaleMatrix;

		for(int i = 0; i < Rings; i++)
		{
			D3DXMatrixScaling(&scaleMatrix, 
				(i+1), 
				(i+1), 
				1.0f);

			D3DXMATRIX finalMatrix = scaleMatrix * Data->World;

			if (Data->Audio.Spectrum[i]*100.0f > 0.8f)
			{
				Line->Begin();
					Line->DrawTransform(Vertices, Segments + 1, &finalMatrix, D3DXCOLOR(
						Data->Audio.Spectrum[i]*(50.0f*Properties.Color.R),
						Data->Audio.Spectrum[i]*(50.0f*Properties.Color.G),
						Data->Audio.Spectrum[i]*(50.0f*Properties.Color.B), 
						Data->Audio.Spectrum[i]*(50.0f*Properties.Color.A)));
				Line->End();
			}
		}
	}
}
 
extern "C" __declspec(dllexport) Manifest* Plugin() {
	return &MosaicPlugin;
}