/*
  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"

glpic_t *pic_cache = NULL;

glpic_t    *conback;
GLuint char_texture;
GLuint translate_texture;

byte menuplyr_pixels[4096];



static glpic_t *Draw_CheckPicCache(const char *identifier)
{
    glpic_t *pic;

    if (!identifier[0])
        return NULL;

    for (pic = pic_cache ; pic ; pic = pic->next)
    {
        if (strcmp(identifier, pic->identifier) == 0)
            return pic;
    }

    return NULL;
}

static glpic_t *Draw_AddToPicCache(const char *identifier, GLuint texnum, unsigned wad_width, unsigned wad_height)
{
    glpic_t *pic;

    if (!identifier[0])
        return NULL;

    pic = (glpic_t *)malloc(sizeof(glpic_t));
    strncpy(pic->identifier, identifier, 128);
    pic->identifier[127] = 0;
    pic->texnum = texnum;
    pic->wad_width = wad_width;
    pic->wad_height = wad_height;

    pic->next = pic_cache;
    pic_cache = pic;

    return pic;
}




glpic_t *Draw_PicFromWad(const char *name)
{
    glpic_t *pic;
    GLuint texnum;
    unsigned width, height;

    pic = Draw_CheckPicCache(name);
    if (pic)
        return pic;

    texnum = R_LoadWadTexture(name, &width, &height);
    if (!texnum)
        return NULL;

    return Draw_AddToPicCache(name, texnum, width, height);
}

glpic_t *Draw_PicFromFile(const char *name)
{
    glpic_t *pic;
    GLuint texnum;
    unsigned width, height;

    pic = Draw_CheckPicCache(name);
    if (pic)
        return pic;

    texnum = R_LoadLumpTexture(name, &width, &height);
    if (!texnum)
        return NULL;

    return Draw_AddToPicCache(name, texnum, width, height);
}


/*
===============
Draw_Init
===============
*/
void Draw_Init(void)
{
    int i;
    byte *conchars;

    // Load the charset by hand, because it has the wrong transparent color
    conchars = (byte *)W_GetLumpName ("conchars");
    for (i=0 ; i<256*64 ; i++)
    {
        if (conchars[i] == 0)
            conchars[i] = 255;
    }

    // Load textures
    char_texture = R_LoadTextureFromData("charset", conchars, 128, 128, TEXTURE_8BIT);
    conback = Draw_PicFromFile("gfx/conback.lmp");
    conback->wad_width = vid.width;
    conback->wad_height = vid.height;

    // save a texture slot for translated picture
    glGenTextures(1, &translate_texture);
}

/*
===============
Draw_Shutdown
===============
*/
void Draw_Shutdown(void)
{
    glpic_t *pic, *next;

    for (pic = pic_cache ; pic ; pic = next)
    {
        next = pic->next;
        free(pic);
    }

    pic_cache = NULL;
}


/*
================
Draw_Character

Draws one 8*8 graphics character with 0 being transparent.
It can be clipped to the top of the screen to allow the console to be
smoothly scrolled off.
================
*/
void Draw_Character (int x, int y, int num)
{
    int                row, col;
    float            frow, fcol, size;

    if (num == 32)
        return;        // space

    num &= 255;

    if (y <= -8)
        return;            // totally off screen

    row = num>>4;
    col = num&15;

    frow = row*0.0625;
    fcol = col*0.0625;
    size = 0.0625;

    glBindTexture(GL_TEXTURE_2D, char_texture);

    glBegin (GL_QUADS);
    glTexCoord2f (fcol, frow);
    glVertex2f (x, y);
    glTexCoord2f (fcol + size, frow);
    glVertex2f (x+8, y);
    glTexCoord2f (fcol + size, frow + size);
    glVertex2f (x+8, y+8);
    glTexCoord2f (fcol, frow + size);
    glVertex2f (x, y+8);
    glEnd ();
}

/*
================
Draw_String
================
*/
void Draw_String (int x, int y, char *str)
{
    while (*str)
    {
        Draw_Character (x, y, *str);
        str++;
        x += 8;
    }
}

/*
=============
Draw_AlphaPic
=============
*/
void Draw_AlphaPic (int x, int y, glpic_t *pic, float alpha)
{
    glColor4f (1,1,1,alpha);
    glBindTexture(GL_TEXTURE_2D, pic->texnum);
    glBegin (GL_QUADS);
    glTexCoord2f (0.0f, 0.0f);
    glVertex2f (x, y);
    glTexCoord2f (1.0f, 0.0f);
    glVertex2f (x+pic->wad_width, y);
    glTexCoord2f (1.0f, 1.0f);
    glVertex2f (x+pic->wad_width, y+pic->wad_height);
    glTexCoord2f (0.0f, 1.0f);
    glVertex2f (x, y+pic->wad_height);
    glEnd ();
    glColor4f (1,1,1,1);
}


/*
=============
Draw_Pic
=============
*/
void Draw_Pic (int x, int y, glpic_t *pic)
{
    glDisable(GL_BLEND);
    glEnable(GL_ALPHA_TEST);

    glColor4f (1,1,1,1);
    glBindTexture(GL_TEXTURE_2D, pic->texnum);
    glBegin (GL_QUADS);
    glTexCoord2f (0.0f, 0.0f);
    glVertex2f (x, y);
    glTexCoord2f (1.0f, 0.0f);
    glVertex2f (x+pic->wad_width, y);
    glTexCoord2f (1.0f, 1.0f);
    glVertex2f (x+pic->wad_width, y+pic->wad_height);
    glTexCoord2f (0.0f, 1.0f);
    glVertex2f (x, y+pic->wad_height);
    glEnd ();

    glDisable(GL_ALPHA_TEST);
    glEnable(GL_BLEND);
}


/*
=============
Draw_TransPicTranslate

Only used for the player color selection menu
=============
*/
void Draw_TransPicTranslate (int x, int y, glpic_t *pic, byte *translation)
{
    unsigned i;
    GLuint tex;
    byte trans[4096];

    for (i = 0 ; i < pic->wad_width * pic->wad_height ; i++)
        trans[i] = translation[menuplyr_pixels[i]];

    tex = R_LoadTextureFromData("", trans, pic->wad_width, pic->wad_height, TEXTURE_8BIT);
    glBindTexture(GL_TEXTURE_2D, tex);

    glColor3f (1,1,1);
    glBegin (GL_QUADS);
    glTexCoord2f (0, 0);
    glVertex2f (x, y);
    glTexCoord2f (1, 0);
    glVertex2f (x+pic->wad_width, y);
    glTexCoord2f (1, 1);
    glVertex2f (x+pic->wad_width, y+pic->wad_height);
    glTexCoord2f (0, 1);
    glVertex2f (x, y+pic->wad_height);
    glEnd ();
}


/*
================
Draw_ConsoleBackground

================
*/
void Draw_ConsoleBackground (int lines)
{
    int y = (vid.height * 3) >> 2;

    if (lines > y)
        Draw_Pic(0, lines - vid.height, conback);
    else
        Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y);
}


/*
=============
Draw_Fill

Fills a box of pixels with a single color
=============
*/
void Draw_Fill (int x, int y, int w, int h, int c)
{
    glDisable (GL_TEXTURE_2D);
    glColor3f (host_basepal[c*3]/255.0,
        host_basepal[c*3+1]/255.0,
        host_basepal[c*3+2]/255.0);

    glBegin (GL_QUADS);

    glVertex2f (x,y);
    glVertex2f (x+w, y);
    glVertex2f (x+w, y+h);
    glVertex2f (x, y+h);

    glEnd ();
    glColor3f (1,1,1);
    glEnable (GL_TEXTURE_2D);
}
//=============================================================================

/*
================
Draw_FadeScreen

================
*/
void Draw_FadeScreen (void)
{
    glDisable (GL_TEXTURE_2D);
    glColor4f (0, 0, 0, 0.8);
    glBegin (GL_QUADS);

    glVertex2f (0,0);
    glVertex2f (vid.width, 0);
    glVertex2f (vid.width, vid.height);
    glVertex2f (0, vid.height);

    glEnd ();
    glColor4f (1,1,1,1);
    glEnable (GL_TEXTURE_2D);
}

//=============================================================================

/*
================
GL_Set2D

Setup as if the screen was 320*200
================
*/
void GL_Set2D (void)
{
    glViewport (0, 0, vid.width, vid.height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity ();
    glOrtho  (0, vid.width, vid.height, 0, -99999, 99999);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity ();

    glDisable (GL_DEPTH_TEST);
    glDisable (GL_CULL_FACE);

    glColor4f (1,1,1,1);
}

