#include "dms/Light.h"

namespace dms
{

int Light::nextLightNum_ = 0;


Light::Light(void)
    {
    if (nextLightNum_ < GL_MAX_LIGHTS)
        {
        lightNumber_ = GL_LIGHT0 + nextLightNum_;
        nextLightNum_++;
        }
    else
        {
        cerr << "Warning: Maximum number of lights exceeded "
            "(maximum is " << GL_MAX_LIGHTS << ")\n";
        lightNumber_ = GL_LIGHT0 + GL_MAX_LIGHTS - 1;
        }
    ambient_.set(0,0,0,1);
    diffuse_.set(1,1,1,1);
    specular_.set(1,1,1,1);
    position_.set(0,0,1,0);
    attenuationConstant_ = 1;
    attenuationLinear_ = 0;
    attenuationQuadratic_ = 0;
    spotDirection_.set(0,0,-1);
    spotCutoff_ = 180;
    spotExponent_ = 0;
    }


void Light::apply(void)
    {
    glEnable(lightNumber_);
    glLightfv(lightNumber_, GL_POSITION, position_.vec);
    glLightfv(lightNumber_, GL_AMBIENT, ambient_.vec);
    glLightfv(lightNumber_, GL_DIFFUSE, diffuse_.vec);
    glLightfv(lightNumber_, GL_SPECULAR, specular_.vec);
    glLightf(lightNumber_, GL_CONSTANT_ATTENUATION, attenuationConstant_);
    glLightf(lightNumber_, GL_LINEAR_ATTENUATION, attenuationLinear_);
    glLightf(lightNumber_, GL_QUADRATIC_ATTENUATION, attenuationQuadratic_);
    glLightf(lightNumber_, GL_SPOT_CUTOFF, spotCutoff_);
    if (spotCutoff_ < 180)
        {
        glLightfv(lightNumber_, GL_SPOT_DIRECTION, spotDirection_.vec);
        glLightf(lightNumber_, GL_SPOT_EXPONENT, spotExponent_);
        }
    }


void Light::enable(void)
    {
    glEnable(lightNumber_);
    }


void Light::disable(void)
    {
    glDisable(lightNumber_);
    }


void Light::setAmbient(const Vector4& color)
    {
    ambient_ = color;
    }


void Light::setDiffuse(const Vector4& color)
    {
    diffuse_ = color;
    }


void Light::setSpecular(const Vector4& color)
    {
    specular_ = color;
    }


void Light::setPosition(const Vector4& position)
    {
    position_ = position;
    }


void Light::setPosition(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
    {
    position_[0] = x;
    position_[1] = y;
    position_[2] = z;
    position_[3] = w;
    }


void Light::setInfinitePosition(const Vector3& position)
    {
    setPosition(position[0], position[1], position[2], 0);
    }


void Light::setInfinitePosition(GLfloat x, GLfloat y, GLfloat z)
    {
    setPosition(x, y, z, 0);
    }


void Light::setLocalPosition(const Vector3& position)
    {
    setPosition(position[0], position[1], position[2], 1);
    }


void Light::setLocalPosition(GLfloat x, GLfloat y, GLfloat z)
    {
    setPosition(x, y, z, 1);
    }


void Light::setAttenuation(GLfloat constant,GLfloat linear,GLfloat quadratic)
    {
    attenuationConstant_ = constant;
    attenuationLinear_ = linear;
    attenuationQuadratic_ = quadratic;
    }


void Light::setSpotDirection(const Vector3& direction)
    {
    spotDirection_ = direction;
    }


void Light::setSpotCutoff(GLfloat cutoff)
    {
    spotCutoff_ = cutoff;
    }


void Light::setSpotExponent(GLfloat exponent)
    {
    spotExponent_ = exponent;
    }

}
