#include <allegro.h>
#include "modules/tilemap.h"
#include "level.h"
#include "objects.h"

int load_level_data_fp(VG_LEVEL * lp, PACKFILE * fp)
{
	int i, j;

	if(fp && lp)
	{
		for(i = 0; i < VG_MAX_OBJECTS; i++)
		{
			lp->object_type[i] = pack_igetl(fp);
			lp->object_x[i] = pack_igetl(fp);
			lp->object_y[i] = pack_igetl(fp);
			lp->object_active[i] = pack_igetl(fp);
			for(j = 0; j < VG_MAX_OBJECT_FLAGS; j++)
			{
				lp->object_flag[i][j] = pack_igetl(fp);
			}
		}
		return 1;
	}
	return 0;
}

int load_level_data(VG_LEVEL * lp, char * fn)
{
    PACKFILE * fp;
    int rval;

    fp = pack_fopen(fn, "rb");
    if(!fp)
    {
        return 0;
    }
    rval = load_level_data_fp(lp, fp);
    pack_fclose(fp);

    return rval;
}

int save_level_data_fp(VG_LEVEL * lp, PACKFILE * fp)
{
	int i, j;

	if(fp && lp)
	{
		for(i = 0; i < VG_MAX_OBJECTS; i++)
		{
			pack_iputl(lp->object_type[i], fp);
			pack_iputl(lp->object_x[i], fp);
			pack_iputl(lp->object_y[i], fp);
			pack_iputl(lp->object_active[i], fp);
			for(j = 0; j < VG_MAX_OBJECT_FLAGS; j++)
			{
				pack_iputl(lp->object_flag[i][j], fp);
			}
		}
		return 1;
	}
	return 0;
}

int save_level_data(VG_LEVEL * lp, char * fn)
{
    PACKFILE * fp;
    int rval;

    fp = pack_fopen(fn, "wb");
    if(!fp)
    {
        return 0;
    }
    rval = save_level_data_fp(lp, fp);
    pack_fclose(fp);

    return rval;
}

int load_level_warps_fp(VG_LEVEL * lp, PACKFILE * fp)
{
	int i, j;

	if(fp && lp)
	{
		for(i = 0; i < VG_MAX_WARPS; i++)
		{
			lp->warp[i].x = pack_igetl(fp);
			lp->warp[i].y = pack_igetl(fp);
			lp->warp[i].dx = pack_igetl(fp);
			lp->warp[i].dy = pack_igetl(fp);
			lp->warp[i].ds = pack_igetl(fp);
			lp->warp[i].type = pack_igetl(fp);
			lp->warp[i].active = pack_getc(fp);
			pack_fread(lp->warp[i].script, 4096, fp);
		}
		return 1;
	}
	return 0;
}

int load_level_warps(VG_LEVEL * lp, char * fn)
{
    PACKFILE * fp;
    int rval;

    fp = pack_fopen(fn, "rb");
    if(!fp)
    {
        return 0;
    }
    rval = load_level_warps_fp(lp, fp);
    pack_fclose(fp);

    return rval;
}

int save_level_warps_fp(VG_LEVEL * lp, PACKFILE * fp)
{
	int i, j;

	if(fp && lp)
	{
		for(i = 0; i < VG_MAX_WARPS; i++)
		{
			pack_iputl(lp->warp[i].x, fp);
			pack_iputl(lp->warp[i].y, fp);
			pack_iputl(lp->warp[i].dx, fp);
			pack_iputl(lp->warp[i].dy, fp);
			pack_iputl(lp->warp[i].ds, fp);
			pack_iputl(lp->warp[i].type, fp);
			pack_putc(lp->warp[i].active, fp);
			pack_fwrite(lp->warp[i].script, 4096, fp);
		}
		return 1;
	}
	return 0;
}

int save_level_warps(VG_LEVEL * lp, char * fn)
{
    PACKFILE * fp;
    int rval;

    fp = pack_fopen(fn, "wb");
    if(!fp)
    {
        return 0;
    }
    rval = save_level_warps_fp(lp, fp);
    pack_fclose(fp);

    return rval;
}

void save_level_fp(VG_LEVEL * lp, PACKFILE * fp)
{
	save_tileset_fp(lp->tileset, fp);
	save_tilemap_fp(lp->tilemap, fp);
	save_level_data_fp(lp, fp);
	save_level_warps_fp(lp, fp);
}

void save_level(VG_LEVEL * lp, char * fn)
{
	PACKFILE * fp;

	fp = pack_fopen(fn, "w");
	if(!fp)
	{
		return;
	}
	save_level_fp(lp, fp);
	pack_fclose(fp);
}

VG_LEVEL * load_level_fp(PACKFILE * fp)
{
	int i;
	VG_LEVEL * lp;

    lp = malloc(sizeof(VG_LEVEL));
    if(!lp)
    {
        return NULL;
    }
	lp->tileset = load_tileset_fp(fp);
	if(!lp->tileset)
	{
		free(lp);
		return NULL;
	}
	lp->tilemap = load_tilemap_fp(fp);
	if(!lp->tilemap)
	{
		return NULL;
	}
	load_level_data_fp(lp, fp);
	load_level_warps_fp(lp, fp);
	initialize_tilemap(lp->tilemap, lp->tileset);
	return lp;
}

VG_LEVEL * load_level(char * fn)
{
	PACKFILE * fp;
	VG_LEVEL * lp;
	char * nfn;
	int i;

	if(!exists(fn))
	{
		nfn = get_filename(fn);
	}
	else
	{
		nfn = fn;
	}
	if(!exists(nfn))
	{
	}
	else
	{
		fp = pack_fopen(nfn, "r");
		if(!fp)
		{
			return NULL;
		}
		lp = load_level_fp(fp);
		pack_fclose(fp);
		for(i = 0; i < VG_MAX_WARPS; i++)
		{
			if(lp->warp[i].active)
			{
				switch(lp->warp[i].type)
				{
					case WARP_TYPE_DOOR:
					case WARP_TYPE_PIPE_DOWN:
					case WARP_TYPE_PIPE_UP:
					case WARP_TYPE_PIPE_LR:
					{
						generate_collision_map(&lp->warp[i].cmap, 0, 0, 16, 16, 16, 16);
						update_collision_map(&lp->warp[i].cmap, lp->warp[i].x, lp->warp[i].y);
						break;
					}
				}
			}
		}

		return lp;
	}
	return NULL;
}

VG_LEVEL * create_level(PALETTE pal, int w, int h, int tw, int th, int l)
{
	int i, j;
	VG_LEVEL * lp;

    clear_keybuf();
    lp = (VG_LEVEL *)malloc(sizeof(VG_LEVEL));
    if(!lp)
    {
        return NULL;
    }
    lp->tileset = create_tileset(pal, tw, th);
    if(!lp->tileset)
    {
	    free(lp);
	    return NULL;
    }
    lp->tilemap = create_tilemap(w, h, l);
    if(!lp->tilemap)
    {
	    destroy_tileset(lp->tileset);
	    free(lp);
	    return NULL;
    }
    initialize_tilemap(lp->tilemap, lp->tileset);
	for(i = 0; i < VG_MAX_OBJECTS; i++)
	{
		lp->object_type[i] = 0;
		lp->object_x[i] = 0;
		lp->object_y[i] = 0;
		lp->object_active[i] = 0;
		for(j = 0; j < VG_MAX_OBJECT_FLAGS; j++)
		{
			lp->object_flag[i][j] = 0;
		}
	}
	for(i = 0; i < VG_MAX_WARPS; i++)
	{
		lp->warp[i].x = 0;
		lp->warp[i].y = 0;
		lp->warp[i].type = 0;
		lp->warp[i].active = 0;
		lp->warp[i].dx = 0;
		lp->warp[i].dy = 0;
		lp->warp[i].ds = 0;
		strcpy(lp->warp[i].script, "");
	}
    return lp;
}

void destroy_level(VG_LEVEL * lp)
{
    if(lp)
    {
    	destroy_tileset(lp->tileset);
       	destroy_tilemap(lp->tilemap);
        free(lp);
    }
}
