/*  DreamChess
**
**  DreamChess is the legal property of its developers, whose names are too
**  numerous to list here. Please refer to the AUTHORS.txt file distributed
**  with this source distribution.
**
**  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 "ui_sdlgl.h"

static texture_t text_characters[256];

texture_t *get_text_character(int index) {
	return &text_characters[index];
}

/** @brief Renders a latin1 character.
 *
 *  @param xpos Leftmost x-coordinate to render the character at.
 *  @param ypos Lowermost y-coordinate to render the character at.
 *  @param scale Size scale factor.
 *  @param character To character to render.
 *  @param col The colour to render with.
 *  @return The width of the textured quad in pixels.
 */
int text_draw_char(float xpos, float ypos, float scale, int character, gg_colour_t *col) {
	int index, offset;
	gg_colour_t black = *get_col(COL_BLACK);

	black.a = col->a;
	offset = 0;
	index = character;

	if (index < 0)
		index += 256;

	draw_texture(&text_characters[index], xpos + 1, ypos - 1, text_characters[index].width * scale,
				 text_characters[index].height * scale, 1.0f, &black);

	draw_texture(&text_characters[index], xpos, ypos, text_characters[index].width * scale,
				 text_characters[index].height * scale, 1.0f, col);

	return text_characters[index].width * scale;
}

/** @brief Renders a latin1 string.
 *
 *  @param xpos Leftmost x-coordinate to render the string at.
 *  @param ypos Lowermost y-coordinate to render the string at.
 *  @param text The string to render.
 *  @param scale Size scale factor.
 *  @param col The colour to render with.
 */
void text_draw_string(float xpos, float ypos, const char *text, float scale, gg_colour_t *col) {
	int i;
	int xposition = xpos;

	for (i = 0; i < strlen(text); i++)
		xposition += text_draw_char(xposition, ypos, scale, text[i], col);
}

static int text_width_n(const char *text, int n) {
	int retval = 0, i;

	for (i = 0; i < n; i++) {
		int index = text[i];

		if (index < 0)
			index += 256;

		retval += text_characters[index].width;
	}

	return retval;
}

/** @brief Returns the width of a string.
 *
 *  @param text String to compute width of.
 *  @return Width of string in pixels.
 */
int text_width(const char *text) {
	return text_width_n(text, strlen(text));
}

/** @brief Returns the font height.
 *
 *  @return Font height in pixels.
 */
int text_height(void) {
	return text_characters['a'].height;
}

/** @brief Renders a latin1 string with right-alignment.
 *
 *  @param xpos Rightmost x-coordinate to render the string at.
 *  @param ypos Lowermost y-coordinate to render the string at.
 *  @param text The string to render.
 *  @param scale Size scale factor.
 *  @param col The colour to render with.
 */
void text_draw_string_right(float xpos, float ypos, const char *text, float scale, gg_colour_t *col) {
	text_draw_string(xpos - text_width(text) * scale, ypos, text, scale, col);
}

/** @brief Renders a bouncy latin1 string.
 *
 *  The bouncing effect is based on BOUNCE_AMP, BOUNCE_LEN and BOUNCE_SPEED.
 *  The current time is used to determine the current animation frame.
 *
 *  @param xpos Leftmost x-coordinate to render the string at.
 *  @param ypos Lowermost y-coordinate to render the string at.
 *  @param text The string to render.
 *  @param scale Size scale factor.
 *  @param col The colour to render with.
 */
void text_draw_string_bouncy(float xpos, float ypos, const char *text, float scale, gg_colour_t *col) {
	int i;
	int xposition = xpos;
	int yposition = ypos;
	Uint32 ticks = SDL_GetTicks();

	for (i = 0; i < strlen(text); i++) {
		float temp_off;
		float phase = ((ticks % (1000 / BOUNCE_SPEED)) / (float)(1000 / BOUNCE_SPEED));

		if (phase < 0.5)
			temp_off = phase * 2 * (BOUNCE_AMP + 1);
		else
			temp_off = ((1.0 - phase) * 2) * (BOUNCE_AMP + 1);

		yposition = ypos + temp_off;
		xposition += text_draw_char(xposition, yposition, scale, text[i], col);

		ticks += 1000 / BOUNCE_SPEED / BOUNCE_LEN;
	}
}

/** @brief Generates textures for the latin1 character set. */
void generate_text_chars(void) {
	int i, j;
	texture_t texture;
	char width[256];
	FILE *f;
	int ypos = 0;
	int tex_height, tex_width;

	load_texture_png(&texture, "font.png", 1, 1);

	tex_height = power_of_two(texture.height);
	tex_width = power_of_two(texture.width);

	f = fopen("font.wid", "rb");

	if (!f) {
		fprintf(stderr, "Couldn't open font width file\n");
		exit(1);
	}

	if (fread(width, 1, 256, f) < 256) {
		fprintf(stderr, "Error reading font width file\n");
		exit(1);
	}

	fclose(f);

	for (i = 0; i < 16; i++) {
		int xpos = 0;

		/* One pixel extra spacing */
		for (j = 0; j < 16; j++) {
			texture_t c;
			c.width = width[i * 16 + j];
			c.height = texture.height / 16 - 1;
			c.u1 = xpos / (float)tex_width;
			c.v1 = ypos / (float)tex_height;
			xpos += width[i * 16 + j];
			c.u2 = (float)xpos / tex_width;
			c.v2 = (ypos + c.height) / (float)tex_height;
			c.id = texture.id;

			xpos++;

			// Scale it back to 480 vertical resolution
			c.width /= 3;
			c.height /= 3;

			text_characters[i * 16 + j] = c;
		}
		ypos += texture.height / 16;
	}
}
