/* sdltools.c
 *
 * SDL Tools
 *
 *
 */

#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <GL/glew.h>
#include "sdltools.h"
#include "math3d.h"
#include "glframe.h"

extern unsigned int maxfps_w;

/* creates a new mouse cursor from an XPM */
const char *arrow[] = {
  /* width height num_colors chars_per_pixel */
  "    32    32        3          1",
  /* colors */
  "X c #000000",
  ". c #ffffff",
  "  c None",
  /* pixels */
  "X                               ",
  "XX                              ",
  "X.X                             ",
  "X..X                            ",
  "X...X                           ",
  "X....X                          ",
  "X.....X                         ",
  "X......X                        ",
  "X.......X                       ",
  "X........X                      ",
  "X.....XXXXX                     ",
  "X..X..X                         ",
  "X.X X..X                        ",
  "XX  X..X                        ",
  "X    X..X                       ",
  "     X..X                       ",
  "      X..X                      ",
  "      X..X                      ",
  "       XX                       ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "                                ",
  "0,0"
};

inline void sdlFrameControl(const unsigned int startclock)
{
    unsigned int deltaclock = SDL_GetTicks() - startclock;
    if (deltaclock < 1000 / maxfps_w)
        SDL_Delay((1000 / maxfps_w) - deltaclock);

#ifdef STAT_FPS
    char buffer[30] = { 0 };
    sprintf(buffer, "%s: %4d fps", window_caption,
            1000 / (SDL_GetTicks() - startclock));
    SDL_WM_SetCaption(buffer, NULL);
#endif
}

SDL_Cursor *sdlInitCursor(const char *image[])
{
    int i, row, col;
    Uint8 data[4*32];
    Uint8 mask[4*32];
    int hot_x, hot_y;

    i = -1;
    for (row = 0; row < 32; ++row)
    {
        for (col = 0; col < 32; ++col)
        {
            if (col % 8)
            {
                data[i] <<= 1;
                mask[i] <<= 1;
            }
            else
            {
                ++i;
                data[i] = mask[i] = 0;
            }

            switch (image[4+row][col])
            {
            case 'X':
                data[i] |= 0x01;
                break;
            case '.':
                mask[i] |= 0x01;
                break;
            case ' ':
                break;
            }
        }
    }

    sscanf(image[4+row], "%d,%d", &hot_x, &hot_y);
    return SDL_CreateCursor(data, mask, 32, 32, hot_x, hot_y);
}

unsigned int sdlTimerCallback(unsigned int interval, void *params)
{
    GLFrame *p = (GLFrame *) params;
    gl_frame_normalize(p);

    return interval;
}

/* load an OpenGL texture from SDL surface */
GLuint sdltLoadGLTexture(SDL_Surface *surface, GLfloat *texcoord)
{
    GLuint texture;
    int w, h;
    SDL_Surface *image;
    SDL_Rect area;
#if 0
    Uint32 saved_flags;
    Uint8 saved_alpha;
#endif

    /* use the surface width and height expanded to powers of 2 */
    w = m3dPowerOfTwo(surface->w);
    h = m3dPowerOfTwo(surface->h);
    texcoord[0] = 0.0f;                     /* min x */
    texcoord[1] = 0.0f;                     /* min y */
    texcoord[2] = (GLfloat) surface->w / w; /* max x */
    texcoord[3] = (GLfloat) surface->h / h; /* max y */

    /* the mask in following line are not big endian aware */
    image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, 0x000000FF, 0x0000FF00, /* XXX */
                                 0x00FF0000, 0xFF000000 /* OpenGL RGBA masks */ );

    if (!image)
        return 0;

#if 0
    /* save the alpha blending attributes */
    saved_flags = surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK);
    SDL_GetSurfaceAlphaMod(surface, &saved_alpha);
    if ((saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA)
        SDL_SetAlpha(surface, 0, 0);
#endif

    /* copy the surface into the GL texture image */
    area.x = 0;
    area.y = 0;
    area.w = surface->w;
    area.h = surface->h;
    SDL_BlitSurface(surface, &area, image, &area);

#if 0
    /* restore the alpha blending attributes */
    if ((saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA)
        SDL_SetAlpha(surface, saved_flags, saved_alpha);
#endif

    /* create an OpenGL texture for the image */
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); /* XXX */
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); /* XXX */
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                 image->pixels);

    SDL_FreeSurface(image);

    return texture;
}