//-----------------------------------------------------------------------------
//
// ImageLib Utility Toolkit Sources
// Copyright (C) 2000-2009 by Denton Woods
// Last modified: 03/07/2009
//
// Filename: src-ILUT/src/ilut_states.c
//
// Description: The state machine
//
//-----------------------------------------------------------------------------


#include "ilut_internal.h"
#include "ilut_states.h"
//#ifdef ILUT_USE_OPENGL
	#include "ilut_opengl.h"
//#endif

ILconst_string _ilutVendor = IL_TEXT("Abysmal Software");
//ILconst_string _ilutVersion	= IL_TEXT("Developer's Image Library Utility Toolkit (ILUT) 1.7.8 " IL_TEXT(__DATE__));
ILconst_string _ilutVersion = IL_TEXT("Developer's Image Library Utility Toolkit (ILUT) 1.7.8");

// Set all states to their defaults
void ilutDefaultStates()
{
    ilutStates[ilutCurrentPos].ilutUsePalettes = IL_FALSE;
    ilutStates[ilutCurrentPos].ilutForceIntegerFormat = IL_FALSE;
    ilutStates[ilutCurrentPos].ilutOglConv = IL_FALSE; // IL_TRUE ?
    ilutStates[ilutCurrentPos].ilutDXTCFormat = 0;
    ilutStates[ilutCurrentPos].ilutUseS3TC = IL_FALSE;
    ilutStates[ilutCurrentPos].ilutGenS3TC = IL_FALSE;
    ilutStates[ilutCurrentPos].ilutAutodetectTextureTarget = IL_FALSE;
    ilutStates[ilutCurrentPos].MaxTexW = 256;
    ilutStates[ilutCurrentPos].MaxTexH = 256;
    ilutStates[ilutCurrentPos].MaxTexD = 1;
    ilutStates[ilutCurrentPos].D3DMipLevels = 0;
    ilutStates[ilutCurrentPos].D3DPool = 0;
    ilutStates[ilutCurrentPos].D3DAlphaKeyColor = -1;
}

void ILAPIENTRY ilutD3D8MipFunc(ILuint NumLevels)
{
    ilutStates[ilutCurrentPos].D3DMipLevels = NumLevels;
    return;
}

ILstring ILAPIENTRY ilutGetString(ILenum StringName)
{
    switch (StringName)
    {
    case ILUT_VENDOR:
        return (ILstring)_ilutVendor;
    //changed 2003-09-04
    case ILUT_VERSION_NUM:
        return (ILstring)_ilutVersion;
    default:
        ilSetError(ILUT_INVALID_PARAM);
        break;
    }
    return NULL;
}

ILboolean ILAPIENTRY ilutEnable(ILenum Mode)
{
    return ilutAble(Mode, IL_TRUE);
}

ILboolean ILAPIENTRY ilutDisable(ILenum Mode)
{
    return ilutAble(Mode, IL_FALSE);
}

ILboolean ilutAble(ILenum Mode, ILboolean Flag)
{
    switch (Mode)
    {
    case ILUT_PALETTE_MODE:
        ilutStates[ilutCurrentPos].ilutUsePalettes = Flag;
        break;

    case ILUT_FORCE_INTEGER_FORMAT:
        ilutStates[ilutCurrentPos].ilutForceIntegerFormat = Flag;
        break;

    case ILUT_OPENGL_CONV:
        ilutStates[ilutCurrentPos].ilutOglConv = Flag;
        break;

    case ILUT_GL_USE_S3TC:
        ilutStates[ilutCurrentPos].ilutUseS3TC = Flag;
        break;

    case ILUT_GL_GEN_S3TC:
        ilutStates[ilutCurrentPos].ilutGenS3TC = Flag;
        break;

    case ILUT_GL_AUTODETECT_TEXTURE_TARGET:
        ilutStates[ilutCurrentPos].ilutAutodetectTextureTarget = Flag;
        break;

    default:
        ilSetError(ILUT_INVALID_ENUM);
        return IL_FALSE;
    }

    return IL_TRUE;
}

ILboolean ILAPIENTRY ilutIsEnabled(ILenum Mode)
{
    switch (Mode)
    {
    case ILUT_PALETTE_MODE:
        return ilutStates[ilutCurrentPos].ilutUsePalettes;

    case ILUT_FORCE_INTEGER_FORMAT:
        return ilutStates[ilutCurrentPos].ilutForceIntegerFormat;

    case ILUT_OPENGL_CONV:
        return ilutStates[ilutCurrentPos].ilutOglConv;

    case ILUT_GL_USE_S3TC:
        return ilutStates[ilutCurrentPos].ilutUseS3TC;

    case ILUT_GL_GEN_S3TC:
        return ilutStates[ilutCurrentPos].ilutGenS3TC;

    case ILUT_GL_AUTODETECT_TEXTURE_TARGET:
        return ilutStates[ilutCurrentPos].ilutAutodetectTextureTarget;

    default:
        ilSetError(ILUT_INVALID_ENUM);
    }

    return IL_FALSE;
}

ILboolean ILAPIENTRY ilutIsDisabled(ILenum Mode)
{
    return !ilutIsEnabled(Mode);
}

void ILAPIENTRY ilutGetBooleanv(ILenum Mode, ILboolean* Param)
{
    switch (Mode)
    {
    case ILUT_PALETTE_MODE:
        *Param = ilutStates[ilutCurrentPos].ilutUsePalettes;
        break;

    case ILUT_FORCE_INTEGER_FORMAT:
        *Param = ilutStates[ilutCurrentPos].ilutForceIntegerFormat;
        break;

    case ILUT_OPENGL_CONV:
        *Param = ilutStates[ilutCurrentPos].ilutOglConv;
        break;

    case ILUT_GL_USE_S3TC:
        *Param = ilutStates[ilutCurrentPos].ilutUseS3TC;
        break;

    case ILUT_GL_GEN_S3TC:
        *Param = ilutStates[ilutCurrentPos].ilutGenS3TC;
        break;

    case ILUT_GL_AUTODETECT_TEXTURE_TARGET:
        *Param = ilutStates[ilutCurrentPos].ilutAutodetectTextureTarget;
        break;

    default:
        ilSetError(ILUT_INVALID_ENUM);
    }
    return;
}

ILboolean ILAPIENTRY ilutGetBoolean(ILenum Mode)
{
    ILboolean Temp = IL_FALSE;
    ilutGetBooleanv(Mode, &Temp);
    return Temp;
}

void ILAPIENTRY ilutGetIntegerv(ILenum Mode, ILint* Param)
{
    switch (Mode)
    {
    /*case IL_ORIGIN_MODE:
			*Param = ilutStates[ilutCurrentPos].ilutOriginMode;
			break;*/
    case ILUT_MAXTEX_WIDTH:
        *Param = ilutStates[ilutCurrentPos].MaxTexW;
        break;
    case ILUT_MAXTEX_HEIGHT:
        *Param = ilutStates[ilutCurrentPos].MaxTexH;
        break;
    case ILUT_MAXTEX_DEPTH:
        *Param = ilutStates[ilutCurrentPos].MaxTexD;
        break;
    case ILUT_VERSION_NUM:
        *Param = ILUT_VERSION;
        break;
    case ILUT_PALETTE_MODE:
        *Param = ilutStates[ilutCurrentPos].ilutUsePalettes;
        break;
    case ILUT_FORCE_INTEGER_FORMAT:
        *Param = ilutStates[ilutCurrentPos].ilutForceIntegerFormat;
        break;
    case ILUT_OPENGL_CONV:
        *Param = ilutStates[ilutCurrentPos].ilutOglConv;
        break;
    case ILUT_GL_USE_S3TC:
        *Param = ilutStates[ilutCurrentPos].ilutUseS3TC;
        break;
    case ILUT_GL_GEN_S3TC:
        *Param = ilutStates[ilutCurrentPos].ilutUseS3TC;
        break;
    case ILUT_S3TC_FORMAT:
        *Param = ilutStates[ilutCurrentPos].ilutDXTCFormat;
        break;
    case ILUT_GL_AUTODETECT_TEXTURE_TARGET:
        *Param = ilutStates[ilutCurrentPos].ilutAutodetectTextureTarget;
        break;
    case ILUT_D3D_MIPLEVELS:
        *Param = ilutStates[ilutCurrentPos].D3DMipLevels;
        break;
    case ILUT_D3D_ALPHA_KEY_COLOR:
        *Param = ilutStates[ilutCurrentPos].D3DAlphaKeyColor;
        break;
    case ILUT_D3D_POOL:
        *Param = ilutStates[ilutCurrentPos].D3DPool;
        break;

    default:
        ilSetError(ILUT_INVALID_ENUM);
    }
    return;
}

ILint ILAPIENTRY ilutGetInteger(ILenum Mode)
{
    ILint Temp = 0;
    ilutGetIntegerv(Mode, &Temp);
    return Temp;
}

void ILAPIENTRY ilutSetInteger(ILenum Mode, ILint Param)
{
    switch (Mode)
    {
    case ILUT_S3TC_FORMAT:
        if (Param >= IL_DXT1 && Param <= IL_DXT5)
        {
            ilutStates[ilutCurrentPos].ilutDXTCFormat = Param;
            return;
        }

    //#ifdef ILUT_USE_OPENGL
    case ILUT_MAXTEX_WIDTH:
        if (Param >= 1)
        {
            ilutStates[ilutCurrentPos].MaxTexW = Param;
            return;
        }
        break;
    case ILUT_MAXTEX_HEIGHT:
        if (Param >= 1)
        {
            ilutStates[ilutCurrentPos].MaxTexH = Param;
            return;
        }
        break;
    case ILUT_MAXTEX_DEPTH:
        if (Param >= 1)
        {
            ilutStates[ilutCurrentPos].MaxTexD = Param;
            return;
        }
        break;
    case ILUT_GL_USE_S3TC:
        if (Param == IL_TRUE || Param == IL_FALSE)
        {
            ilutStates[ilutCurrentPos].ilutUseS3TC = (ILboolean)Param;
            return;
        }
        break;
    case ILUT_GL_GEN_S3TC:
        if (Param == IL_TRUE || Param == IL_FALSE)
        {
            ilutStates[ilutCurrentPos].ilutGenS3TC = (ILboolean)Param;
            return;
        }
        break;
    case ILUT_GL_AUTODETECT_TEXTURE_TARGET:
        if (Param == IL_TRUE || Param == IL_FALSE)
        {
            ilutStates[ilutCurrentPos].ilutAutodetectTextureTarget = (ILboolean)Param;
            return;
        }
        break;
    //#endif//ILUT_USE_OPENGL

    //#ifdef ILUT_USE_DIRECTX8
    case ILUT_D3D_MIPLEVELS:
        if (Param >= 0)
        {
            ilutStates[ilutCurrentPos].D3DMipLevels = Param;
            return;
        }
        break;

    case ILUT_D3D_ALPHA_KEY_COLOR:
        ilutStates[ilutCurrentPos].D3DAlphaKeyColor = Param;
        return;
        break;

    case ILUT_D3D_POOL:
        if (Param >= 0 && Param <= 2)
        {
            ilutStates[ilutCurrentPos].D3DPool = Param;
            return;
        }
        break;
    //#endif//ILUT_USE_DIRECTX8

    default:
        ilSetError(ILUT_INVALID_ENUM);
    }

    ilSetError(IL_INVALID_PARAM); // Parameter not in valid bounds.
    return;
}

void ILAPIENTRY ilutPushAttrib(ILuint Bits)
{
    // Should we check here to see if ilCurrentPos is negative?

    if (ilutCurrentPos >= ILUT_ATTRIB_STACK_MAX - 1)
    {
        ilutCurrentPos = ILUT_ATTRIB_STACK_MAX - 1;
        ilSetError(ILUT_STACK_OVERFLOW);
        return;
    }

    ilutCurrentPos++;

    //memcpy(&ilutStates[ilutCurrentPos], &ilutStates[ilutCurrentPos - 1], sizeof(ILUT_STATES));

    if (Bits & ILUT_OPENGL_BIT)
    {
        ilutStates[ilutCurrentPos].ilutUsePalettes = ilutStates[ilutCurrentPos - 1].ilutUsePalettes;
        ilutStates[ilutCurrentPos].ilutOglConv = ilutStates[ilutCurrentPos - 1].ilutOglConv;
    }
    if (Bits & ILUT_D3D_BIT)
    {
        ilutStates[ilutCurrentPos].D3DMipLevels = ilutStates[ilutCurrentPos - 1].D3DMipLevels;
        ilutStates[ilutCurrentPos].D3DAlphaKeyColor = ilutStates[ilutCurrentPos - 1].D3DAlphaKeyColor;
    }

    return;
}

void ILAPIENTRY ilutPopAttrib()
{
    if (ilutCurrentPos <= 0)
    {
        ilutCurrentPos = 0;
        ilSetError(ILUT_STACK_UNDERFLOW);
        return;
    }

    // Should we check here to see if ilutCurrentPos is too large?
    ilutCurrentPos--;

    return;
}

ILboolean ILAPIENTRY ilutRenderer(ILenum Renderer)
{
    if (Renderer > ILUT_WIN32)
    {
        ilSetError(ILUT_INVALID_VALUE);
        return IL_FALSE;
    }

    switch (Renderer)
    {
		#ifdef ILUT_USE_OPENGL
    case ILUT_OPENGL:
        return ilutGLInit();
		#endif

		#ifdef ILUT_USE_WIN32
    case ILUT_WIN32:
        return ilutWin32Init();
		#endif

		#ifdef ILUT_USE_DIRECTX8
    case ILUT_DIRECT3D8:
        return ilutD3D8Init();
		#endif

		#ifdef ILUT_USE_DIRECTX9
    case ILUT_DIRECT3D9:
        return ilutD3D9Init();
        #endif
		
		#ifdef ILUT_USE_DIRECTX10
    case ILUT_DIRECT3D10:
        return ilutD3D10Init();
        #endif

    default:
        ilSetError(ILUT_NOT_SUPPORTED);
    }

    return IL_FALSE;
}
