#include "PointLight.h"

PointLight::PointLight(Vertex lightPosition) : Light()
{
	_lightPosition = lightPosition;
	SetAttenuation(0, 0, 0);
}

PointLight::PointLight(Vertex lightPosition, float a, float b, float c) : Light(255, 255, 255)
{
	_lightPosition = lightPosition;
	SetAttenuation(a, b, c);
}

PointLight::PointLight(Vertex lightPosition, float a, float b, float c, int red, int green, int blue) : Light(red, green, blue)
{
	_lightPosition = lightPosition;
	SetAttenuation(a, b, c);
}

PointLight::PointLight(const PointLight& other) : Light(other)
{
	Copy(other);
}

void PointLight::SetAttenuation(float a, float b, float c)
{
	_attenuationA = a;
	_attenuationB = b;
	_attenuationC = c;
}

void PointLight::SetAttenuationA(float value)
{
	_attenuationA = value;
}

void PointLight::SetAttenuationB(float value)
{
	_attenuationB = value;
}

void PointLight::SetAttenuationC(float value)
{
	_attenuationC = value;
}

float PointLight::GetAttenuationA()
{
	return _attenuationA;
}

float PointLight::GetAttenuationB()
{
	return _attenuationB;
}

float PointLight::GetAttenuationC()
{
	return _attenuationC;
}

void PointLight::SetLightPosition(float x, float y, float z)
{
	SetLightPosition(Vertex(x, y, z));
}

void PointLight::SetLightPosition(Vertex Position)
{
	_lightPosition = Position;
}

Vertex PointLight::GetLightPosition() const
{
	return _lightPosition;
}

COLORREF PointLight::CalculateLightShared(const Model& currentModel, const Vertex& currentVertex, const Vector3D& currentNormal, COLORREF colorIn)
{
	float workingRed = (float)GetRedLightIntensity();
	float workingGreen = (float)GetGreenLightIntensity();
	float workingBlue = (float)GetBlueLightIntensity();

	float fudge = 100;

	workingRed *= currentModel.GetRedReflectionCoefficient();
	workingGreen *= currentModel.GetGreenReflectionCoefficient();
	workingBlue *= currentModel.GetBlueReflectionCoefficient();

	Vector3D lightSource = currentVertex - _lightPosition;
	Vector3D lightSourceNormalized = lightSource;
	lightSourceNormalized.Normalize();

	float distance = Vector3D::Length(currentNormal, lightSource);

	float lightDotProd = Vector3D::DotProduct(lightSourceNormalized, currentNormal);
	float attenuation = 1 / (GetAttenuationA() + GetAttenuationB() * distance + GetAttenuationC() * (distance * distance));

	workingRed *= lightDotProd;
	workingGreen *= lightDotProd;
	workingBlue *= lightDotProd;

	workingRed *= attenuation;
	workingGreen *= attenuation;
	workingBlue *= attenuation;

	workingRed *= fudge;
	workingGreen *= fudge;
	workingBlue *= fudge;

	workingRed += (float)GetRValue(colorIn);
	workingGreen += (float)GetGValue(colorIn);
	workingBlue += (float)GetBValue(colorIn);

	int finalRed = BoundsCheck(0, 255, (int)workingRed);
	int finalGreen = BoundsCheck(0, 255, (int)workingGreen);
	int finalBlue = BoundsCheck(0, 255, (int)workingBlue);
	COLORREF outputColor = RGB(finalRed, finalGreen, finalBlue);

	return outputColor;
}

COLORREF PointLight::CalculateLight(const Model& currentModel, const Polygon3D& currentPolygon, COLORREF colorIn)
{
	return CalculateLightShared(currentModel, currentModel.GetVertex(currentPolygon.GetIndex(0)), currentPolygon.GetNormal(), colorIn);
}

COLORREF PointLight::CalculateLight(const Model& currentModel, const Vertex& currentVertex, COLORREF colorIn)
{
	return CalculateLightShared(currentModel, currentVertex, currentVertex.GetNormal(), colorIn);
}

PointLight& PointLight::operator= (const PointLight& rhs)
{
	if (this != &rhs)
	{
		Copy(rhs);
	}
	return *this;
}

void PointLight::Copy(const PointLight& other)
{
	_lightPosition = other.GetLightPosition();
	Light::Copy(other);
}
