#include <allegro.h>
#include "message.h"
#include "modules/ncds.h"
#include "control.h"
#include "level.h"
#include "modules/tilemap.h"
#include "modules/colormap.h"
#include "title.h"
#include "level.h"
#include "objects.h"
#include "warp.h"
#include "data.h"
#include "projectile.h"
#include "sprite.h"
#include "progress.h"
#include "menu.h"

float             VG_CHARACTER_JUMP_VELOCITY = -6.0;
float             VG_CHARACTER_GRAVITY = 0.29;
VG_MENU           vg_menu[VG_MAX_MENUS];
int               vg_current_menu = VG_MENU_MAIN;
VG_PROGRESS_INFO  vg_progress;
int               vg_done = 0;
ANIMATION *       vg_animation[VG_MAX_ANIMATIONS] = {NULL};
BITMAP *          vg_image[VG_MAX_IMAGES] = {NULL};
VG_CHARACTER      vg_player;
VG_PROJECTILE     vg_projectile[VG_MAX_PROJECTILES];
VG_SPRITE_DATA *  vg_sprite_data[VG_MAX_SPRITE_DATA] = {NULL};
VG_SPRITE         vg_sprite[VG_MAX_OBJECTS];
CONTROLLER        vg_controller;
BITMAP *          vg_screen = NULL;
PALETTE           vg_palette;
COLOR_MAP         vg_color_map;
COLOR_MAP         vg_light_map;
int               vg_state = VG_STATE_TITLE;
int               vg_quit = 0;
int               vg_global_frame = 0;
VG_LEVEL *        vg_level = NULL;
SAMPLE *          vg_sound[VG_MAX_SOUNDS] = {NULL};
FONT *            vg_font[VG_MAX_FONTS] = {NULL};

VG_WARP           vg_last_warp;

void lighting_blender(PALETTE pal, int x, int y, RGB *rgb)
{
	int light;
	fixed light_level;
	fixed col_level;
	int final;
	fixed left;
	
	/* calculate the total luminence of the color */
	light = (pal[x].r + pal[x].g + pal[x].b) / 3;
	
	/* do shadow blend */
	if(light == 0)
	{
		rgb->r = 0;
		rgb->g = 0;
		rgb->b = 0;
	}
	else if(light < 32)
	{
		rgb->r = fixtoi(fmul(itofix(pal[y].r), fdiv(itofix(light * 2 + 1), itofix(63))));
		rgb->g = fixtoi(fmul(itofix(pal[y].g), fdiv(itofix(light * 2 + 1), itofix(63))));
		rgb->b = fixtoi(fmul(itofix(pal[y].b), fdiv(itofix(light * 2 + 1), itofix(63))));
	}
	
	/* do light blend */
	else if(light == 32)
	{
		rgb->r = pal[y].r;
		rgb->g = pal[y].g;
		rgb->b = pal[y].b;
	}
	else
	{
		light_level = fdiv(itofix((light - 32) * 2 + 1), itofix(63));
		left = itofix(63 - pal[y].r);
		final = pal[y].r + fixtoi(fmul(left, light_level));
		rgb->r = final;
		left = itofix(63 - pal[y].g);
		final = pal[y].g + fixtoi(fmul(left, light_level));
		rgb->g = final;
		left = itofix(63 - pal[y].b);
		final = pal[y].b + fixtoi(fmul(left, light_level));
		rgb->b = final;
	}
}

void generate_flame_bar(VG_SPRITE * sp)
{
	int i, j, flame_count = 0;
	int offsets[8] = {0, 8, 16, 24, 32, 40, 48, 56};
	
	for(i = 0; i < VG_MAX_OBJECTS && flame_count < 8; i++)
	{
		if(!vg_sprite[i].active)
		{
			vg_sprite[i].type = VG_SPRITE_FLAME;
			vg_sprite[i].sp = vg_sprite_data[vg_sprite[i].type];
			vg_sprite[i].x = sp->x;
			vg_sprite[i].y = sp->y - itofix(offsets[flame_count]);
			vg_sprite[i].vx = itofix(0);
			vg_sprite[i].vy = itofix(0);
			vg_sprite[i].active = 1;
			vg_sprite[i].d1 = sp->id;
			vg_sprite[i].d2 = offsets[flame_count];
			vg_sprite[i].frame = 0;
			vg_sprite[i].timer = 0;
			vg_sprite[i].state = 0;
			vg_sprite[i].angle = itofix(0);
			vg_sprite[i].id = i;
			vg_sprite[i].death = 0;
			for(j = 0; j < VG_SPRITE_MAX_STATES; j++)
			{
				generate_collision_map(&vg_sprite[i].cmap[j], vg_sprite_data[vg_sprite[i].type]->cx[0], vg_sprite_data[vg_sprite[i].type]->cy[0], vg_sprite_data[vg_sprite[i].type]->cw[0], vg_sprite_data[vg_sprite[i].type]->ch[0], 16, 16);
				update_collision_map(&vg_sprite[i].cmap[j], fixtoi(vg_sprite[i].x), fixtoi(vg_sprite[i].y));
			}
			flame_count++;
			printf("flame added (%d,%d)\n", fixtoi(vg_sprite[i].x), fixtoi(vg_sprite[i].y));
		}
	}
}

void read_level_data(VG_LEVEL * lp)
{
	int i, j;
	
	for(i = 0; i < VG_MAX_OBJECTS; i++)
	{
		if(lp->object_active[i])
		{
			vg_sprite[i].type = lp->object_type[i];
			vg_sprite[i].sp = vg_sprite_data[vg_sprite[i].type];
			vg_sprite[i].x = itofix(lp->object_x[i]);
			vg_sprite[i].y = itofix(lp->object_y[i]);
			vg_sprite[i].vx = vg_progress.difficulty == 0 ? ftofix(-0.75) : itofix(-1);
			vg_sprite[i].active = 1;
			if(vg_sprite_data[vg_sprite[i].type])
			{
				for(j = 0; j < VG_SPRITE_MAX_STATES; j++)
				{
					generate_collision_map(&vg_sprite[i].cmap[j], vg_sprite_data[vg_sprite[i].type]->cx[0], vg_sprite_data[vg_sprite[i].type]->cy[0], vg_sprite_data[vg_sprite[i].type]->cw[0], vg_sprite_data[vg_sprite[i].type]->ch[0], 16, 16);
					update_collision_map(&vg_sprite[i].cmap[j], fixtoi(vg_sprite[i].x), fixtoi(vg_sprite[i].y));
				}
			}
			vg_sprite[i].state = 0;
			vg_sprite[i].angle = itofix(0);
			vg_sprite[i].id = i;
			vg_sprite[i].death = 0;
			vg_sprite[i].frame = 0;
		}
		else
		{
			vg_sprite[i].active = 0;
		}
	}
	
	/* search for sprites that have special startup sequences */
	for(i = 0; i < VG_MAX_OBJECTS; i++)
	{
		if(vg_sprite[i].active)
		{
			switch(vg_sprite[i].type)
			{
				case VG_SPRITE_FLAME_PIVOT:
				{
					generate_flame_bar(&vg_sprite[i]);
					break;
				}
				case VG_SPRITE_MARIO:
				{
					vg_sprite[i].life = 100;
					break;
				}
			}
		}
	}
}

void vg_load_data(void)
{
	int i, j;
	char temp_string[256] = {0};

	/* create the translucency map */
	destroy_bitmap(load_pcx("palette.pcx", vg_palette));
	select_palette(vg_palette);
	load_color_map(&vg_color_map, "trans.cmp");
	color_map = &vg_color_map;
	create_color_table(&vg_light_map, vg_palette, (void *)lighting_blender, NULL);
	tilemap_trans_color_map = &vg_color_map;
	tilemap_light_map = &vg_light_map;
	vg_image[VG_IMAGE_TITLE] = load_pcx("title.pcx", NULL);
	vg_image[VG_IMAGE_LSELECT] = load_pcx("lselect.pcx", NULL);
	vg_sound[VG_SOUND_PLAYER_JUMP] = load_wav("jump.wav");
	vg_sound[VG_SOUND_PLAYER_KILL] = load_wav("kill.wav");
	vg_sound[VG_SOUND_PLAYER_WARP] = load_wav("warppipe.wav");
	vg_sound[VG_SOUND_PLAYER_BULLET] = load_wav("bullet.wav");
	vg_sound[VG_SOUND_PLAYER_DIE] = load_wav("die.wav");
	vg_sound[VG_SOUND_PLAYER_SHOOT] = load_wav("shoot.wav");
	vg_sound[VG_SOUND_PLAYER_COIN] = load_wav("coin.wav");
	vg_font[VG_FONT_MENU] = load_font("menufont.pcx", NULL, NULL);
	vg_font[VG_FONT_GAME] = load_font("gamefont.pcx", NULL, NULL);
	vg_sprite_data[VG_SPRITE_GOOMBA] = vg_sprite_load("goomba.spr");
	vg_sprite_data[VG_SPRITE_DEATH] = vg_sprite_load("death.spr");
	vg_sprite_data[VG_SPRITE_TURTLE] = vg_sprite_load("turtle.spr");
	vg_sprite_data[VG_SPRITE_THWOMP] = vg_sprite_load("thwomp.spr");
	vg_sprite_data[VG_SPRITE_BULLET] = vg_sprite_load("bullet.spr");
	vg_sprite_data[VG_SPRITE_BEETLE] = vg_sprite_load("beetle.spr");
	vg_sprite_data[VG_SPRITE_FLAME] = vg_sprite_load("flame.spr");
	vg_sprite_data[VG_SPRITE_COIN] = vg_sprite_load("coin.spr");
	vg_sprite_data[VG_SPRITE_RTURTLE] = vg_sprite_load("rturtle.spr");
	vg_sprite_data[VG_SPRITE_MARIO] = vg_sprite_load("mario.spr");
	vg_sprite_data[VG_SPRITE_QBLOCK] = vg_sprite_load("qblock.spr");
	
	/* load animations */
	vg_animation[VG_ANIMATION_PSHOT] = load_ani("bullet.ani", NULL);
	vg_animation[VG_ANIMATION_MSHOT] = load_ani("fireball.ani", NULL);

	/* load the character */
	
	vg_sprite_data[VG_SPRITE_PLAYER] = vg_sprite_load("player.spr");
	vg_player.sprite.sp = vg_sprite_data[VG_SPRITE_PLAYER];
	for(i = 0; i < 16; i++)
	{
		generate_collision_map(&vg_player.sprite.cmap[i], vg_sprite_data[VG_SPRITE_PLAYER]->cx[i], vg_sprite_data[VG_SPRITE_PLAYER]->cy[i], vg_sprite_data[VG_SPRITE_PLAYER]->cw[i], vg_sprite_data[VG_SPRITE_PLAYER]->ch[i], 16, 16);
	}
	menu_setup();
}

void vg_free_data(void)
{
	int i;
	
	for(i = 0; i < VG_MAX_SPRITE_DATA; i++)
	{
		if(vg_sprite_data[i])
		{
			vg_sprite_destroy(vg_sprite_data[i]);
		}
	}
	for(i = 0; i < VG_MAX_IMAGES; i++)
	{
		if(vg_image[i])
		{
			destroy_bitmap(vg_image[i]);
		}
	}
	for(i = 0; i < VG_MAX_ANIMATIONS; i++)
	{
		if(vg_animation[i])
		{
			destroy_ani(vg_animation[i]);
		}
	}
	for(i = 0; i < VG_MAX_SOUNDS; i++)
	{
		if(vg_sound[i])
		{
			destroy_sample(vg_sound[i]);
		}
	}
	if(vg_level)
	{
		destroy_level(vg_level);
	}
}
