/*
  Copyright (C) 2010-2011  Charles Pence <charles@charlespence.net>
  Copyright (C) 1996-1997  Id Software, Inc.

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "pch.h"
#include "quakedef.h"


byte    dottexture[8][8] =
{
    {0,1,1,0,0,0,0,0},
    {1,1,1,1,0,0,0,0},
    {1,1,1,1,0,0,0,0},
    {0,1,1,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
};
void R_InitParticleTexture (void)
{
    int        x,y;
    byte    data[8][8][4];

    //
    // particle texture
    //
    for (x=0 ; x<8 ; x++)
    {
        for (y=0 ; y<8 ; y++)
        {
            data[y][x][0] = 255;
            data[y][x][1] = 255;
            data[y][x][2] = 255;
            data[y][x][3] = dottexture[x][y]*255;
        }
    }

    particletexture = R_LoadTextureFromData("particle", &data[0][0][0], 8, 8, TEXTURE_RGBA);
}

/*
===============
R_Init
===============
*/
void R_Init (void)
{
    Cmd_AddCommand("timerefresh", R_TimeRefresh_f);

    Cvar_RegisterVariable("r_norefresh", "0");
    Cvar_RegisterVariable("r_lightmap", "0");
    Cvar_RegisterVariable("r_fullbright", "0");
    Cvar_RegisterVariable("r_drawentities", "1");
    Cvar_RegisterVariable("r_drawviewmodel", "1");
    Cvar_RegisterVariable("r_wateralpha", "0.7");
    Cvar_RegisterVariable("r_dynamic", "1");
    Cvar_RegisterVariable("r_novis", "0");
    Cvar_RegisterVariable("r_speeds", "0");
    Cvar_RegisterVariable("r_skybox", "0");
    Cvar_RegisterVariable("r_skyname", "purple_chaos_");

    Cvar_RegisterVariable("gl_cull", "1");
    Cvar_RegisterVariable("gl_polyblend", "1");
    Cvar_RegisterVariable("gl_nocolors", "0");

    R_InitTextures();
    R_InitParticles();
    R_InitParticleTexture();
}

/*
===============
R_Shutdown
===============
*/
void R_Shutdown(void)
{
    R_ShutdownTextures();
}


/*
===============
R_TranslatePlayerSkin

Translates a skin texture by the per-player color lookup
===============
*/
void R_TranslatePlayerSkin (int playernum)
{
    int        top, bottom;
    byte    translate[256];
    int        i;
    model_t    *model;
    aliashdr_t *paliashdr;
    byte    *original, *translated;
    int            inwidth, inheight;

    top = cl.scores[playernum].colors & 0xf0;
    bottom = (cl.scores[playernum].colors &15)<<4;

    for (i=0 ; i<256 ; i++)
        translate[i] = i;

    for (i=0 ; i<16 ; i++)
    {
        if (top < 128)    // the artists made some backwards ranges.  sigh.
            translate[TOP_RANGE+i] = top+i;
        else
            translate[TOP_RANGE+i] = top+15-i;

        if (bottom < 128)
            translate[BOTTOM_RANGE+i] = bottom+i;
        else
            translate[BOTTOM_RANGE+i] = bottom+15-i;
    }

    //
    // locate the original skin pixels
    //
    currententity = &cl_entities[1+playernum];
    model = currententity->model;
    if (!model)
        return;    // player doesn't have a model yet
    if (model->type != mod_alias)
        return; // only translate skins on alias models

    paliashdr = (aliashdr_t *)Mod_Extradata (model);
    if (currententity->skinnum < 0 || currententity->skinnum >= paliashdr->numskins)
    {
        Con_Printf("(%d): Invalid player skin #%d\n", playernum, currententity->skinnum);
        original = (byte *)paliashdr + paliashdr->texels[0];
        translated = (byte *)paliashdr + paliashdr->trans_texels[0];
    }
    else
    {
        original = (byte *)paliashdr + paliashdr->texels[currententity->skinnum];
        translated = (byte *)paliashdr + paliashdr->trans_texels[currententity->skinnum];
    }

    inwidth = paliashdr->skinwidth;
    inheight = paliashdr->skinheight;

    for (i=0 ; i < inwidth*inheight ; i++)
        translated[i] = translate[original[i]];

    playertextures[playernum] = R_LoadTextureFromData("", translated, inwidth, inheight, TEXTURE_8BIT);
}


/*
===============
R_NewMap
===============
*/
void R_NewMap (void)
{
    int        i;

    for (i=0 ; i<256 ; i++)
        d_lightstylevalue[i] = 264;        // normal light value

// clear out efrags in case the level hasn't been reloaded
// FIXME: is this one short?
    for (i=0 ; i<cl.worldmodel->numleafs ; i++)
        cl.worldmodel->leafs[i].efrags = NULL;

    r_viewleaf = NULL;
    R_ClearParticles ();

    GL_BuildLightmaps ();

    // Clear all texture chains
    for (i=0 ; i<cl.worldmodel->numtextures ; i++)
    {
        if (!cl.worldmodel->textures[i])
            continue;
         cl.worldmodel->textures[i]->texturechain = NULL;
    }

    // FIXME SKYBOX
    //R_LoadSkys ();
}


/*
====================
R_TimeRefresh_f

For program optimization
====================
*/
void R_TimeRefresh_f (void)
{
    int            i;
    float        start, stop, time;

    glDrawBuffer  (GL_FRONT);
    glFinish ();

    start = Sys_FloatTime ();
    for (i=0 ; i<128 ; i++)
    {
        r_refdef.viewangles[1] = i/128.0*360.0;
        R_RenderView ();
    }

    glFinish ();
    stop = Sys_FloatTime ();
    time = stop-start;
    Con_Printf ("%f seconds (%f fps)\n", time, 128/time);

    glDrawBuffer  (GL_BACK);
    GL_EndRendering ();
}
