#include <fstream>
#include <allegro.h>
#include "CMap.hpp"
#include "CDisplay.hpp"
#include "CPlayer.hpp"
#include "Interaction.hpp"
#include "Quests.hpp"
#include "CMenu.hpp"
#include <fblend.h>

#include "CBattle.hpp"
#include "CCine.hpp"

CPortal::CPortal()
{
  	srcx = 0;
	srcy = 0;

    destx = 0;
	desty = 0;
    cine_id = 0;
    check_quest = 0;
    
	name = "Null";
}

CMap::CMap()
{
        name = "NULL";
        tileset_name = "NULL";
        spriteset_name = "NULL";
		
		/* defaults */
		sizew = 16;
		sizeh = 16; 
		
		config = 2;
		
		max_portal = 0;
		max_event = 0;
		max_npc = 0;
		
        player_start_x = 0;
        player_start_y = 0;
        
        player1_start_x = 0;
        player1_start_y = 0;
        
        battle_destmap = "empty";
        battle_x = 0;
        battle_y = 0;
        
        isbattle = false;
        cine_id = 0;

//        special_tiles[TILE_ITEM] = load_bitmap("./data/special.bmp", NULL);
}

CMap::~CMap()
{
}


// Resizes the 3d array that holds the CTile information for the map...
// [layer][y][x]
void CMap::ResizeMap()
{
        tile.resize(layers);

        for(dword i = 0; i!=layers; i++)
        {
                tile[i].resize(h);

                for(dword j = 0; j!=h; j++)
                {
                        tile[i][j].resize(w);
                }

        }

}

void CMap::ResizeMap(int layer, int width, int height)
{
        tile.resize(layer);

        for(dword i = 0; i!=layer; i++)
        {
                tile[i].resize(height);

                for(dword j = 0; j!=height; j++)
                {
                        tile[i][j].resize(width);
                }

        }

}


dword CMap::GetWidth()
{
  return w;
}

dword CMap::GetHeight()
{
  return h;
}

byte CMap::GetLayers()
{
  return layers;
}

void CMap::ClearMap()
{
    max_portal = 0;
	max_event = 0;
	max_npc = 0;

    player_start_x = 0;
    player_start_y = 0;

    player1_start_x = 0;
    player1_start_y = 0;

    battle_destmap = "empty";
    battle_x = 0;
    battle_y = 0;

    isbattle = false;
    cine_id = 0;
}

int CMap::LoadMap(std::string filename)
{
    LoadMap(filename, false);
}

/* Seems a little bulky eh? */
int CMap::LoadMap(std::string filename, bool iscine)
{
        ClearMap();
        FILE *fin = fopen( (filename.c_str()), "rb");

        if(!fin) allegro_message("Error: Couldn't find the map to load! %s", filename.c_str());

        char *temp = new char[255];
        fscanf(fin, "Name: %s\n", temp);
                name = temp;
        fscanf(fin, "Tileset: %s\n", temp);
                tileset_name = temp;
                LoadTileset(tileset_name.c_str());
        fscanf(fin, "Spriteset: %s\n", temp);
                spriteset_name = temp;
                LoadSpriteset(spriteset_name.c_str());


        // TODO: make the basic framework first then do this
        /* Name of map that it points to after winning */

        /* Width */
                fread(&w, sizeof(dword), 1, fin);

        /* Height */
                fread(&h, sizeof(dword), 1, fin);

        /* Layers */
              fread(&layers, sizeof(byte), 1, fin);

        /* Tile Width and Tile Height */
                fread(&sizew, sizeof(dword), 1, fin);
                fread(&sizeh, sizeof(dword), 1, fin);
		
		fread(&config, sizeof(int), 1, fin);
		
     	fread(&isbattle, sizeof(bool), 1, fin);
     	fread(&cine_id, sizeof(int), 1, fin);
     	fread(&player_start_x, sizeof(dword), 1, fin);
     	fread(&player_start_y, sizeof(dword), 1, fin);
     	
    	fread(&player1_start_x, sizeof(dword), 1, fin);
     	fread(&player1_start_y, sizeof(dword), 1, fin);
     	
		char name_holder[1024];
		

/*        for(int j = 0; j<255; ++j) name_holder[j] = ' ';
        fread(name_holder, 1,255), fin);
        battle_destmap = name_holder;
        */

        fscanf(fin, "\nBDestmap: %s\n", temp);
                battle_destmap = temp;
                
     	fread(&battle_x, sizeof(dword), 1, fin);
   	   	fread(&battle_y, sizeof(dword), 1, fin);

		// TODO: See if there's a better way than to read/write the max # of portals (automatically get the max position in the vector?)
		fread(&max_portal, sizeof(dword), 1, fin);
		portal.resize(max_portal);
		for(dword i = 0; i < max_portal; ++i)
		{
			fread(&portal[i].srcx, sizeof(dword), 1, fin);
			fread(&portal[i].srcy, sizeof(dword), 1, fin);
			fread(&portal[i].destx, sizeof(dword), 1, fin);
			fread(&portal[i].desty, sizeof(dword), 1, fin);
			fread(&portal[i].cine_id, sizeof(dword), 1, fin);
    		fread(&portal[i].check_quest, sizeof(dword), 1, fin);

            for(int j = 0; j<255; ++j) name_holder[j] = ' ';
	        fread(name_holder, 1,255, fin);
            portal[i].name = name_holder;

		}

		fread(&max_event, sizeof(dword), 1, fin);
		event.resize(max_event);
		for(dword i = 0; i < max_event; ++i)
		{
			fread(&event[i].x, sizeof(dword), 1, fin);
			fread(&event[i].y, sizeof(dword), 1, fin);
			fread(&event[i].flags, sizeof(dword), 1, fin);
    		fread(&event[i].id, sizeof(int), 1, fin);
            for(int j = 0; j<255; ++j) name_holder[j] = ' ';
            fread(name_holder, 1,255, fin);
            event[i].name = name_holder;
            for(int j = 0; j<1024; ++j) name_holder[j] = ' ';
            fread(name_holder, 1,1024, fin);
            event[i].text = name_holder;
            for(int j = 0; j<1024; ++j) name_holder[j] = ' ';
            fread(name_holder, 1,1024, fin);
            event[i].posttext = name_holder;
		}

		fread(&max_npc, sizeof(dword), 1, fin);
		npc.resize(max_npc);
		for(dword i = 0; i < max_npc; ++i)
		{
			fread(&npc[i].x, sizeof(dword), 1, fin);
			fread(&npc[i].y, sizeof(dword), 1, fin);
			fread(&npc[i].flags, sizeof(dword), 1, fin);
			fread(&npc[i].gfx, sizeof(byte), 1, fin);
        	fread(&npc[i].id, sizeof(int), 1, fin);

/* TODO: depends on how I do the quest
               if(npc[i].gfx == 4)
               {
                     std::vector<CNpc>::iterator pos;
                     pos = map.event.begin() + i;
                     map.npc.erase(pos);
                     map.max_npc--;
               }
*/
		}
		
		for(int i = 0; i<max_npc; ++i)
		{
		  	if( !iscine)
        	{
             	if(npc[i].gfx == 3)
                 {
                     std::vector<CNpc>::iterator pos;
                     pos = map.npc.begin() + i;
                     map.npc.erase(pos);
                     map.max_npc--;
                 }
            }
        }
        /* Setup anything that we missed, clear arrays etc */
        InitMap(w, h, sizew, sizeh, layers);

for(dword v=0; v<tile.size(); v++)			// layer
 for(dword i=0; i<tile[0].size(); i++)		        // y(height)
   for(dword j=0; j<tile[0][0].size(); j++)		// x(width)
   {
           fread(&tile[v][i][j].gfx, sizeof(dword), 1, fin);
           fread(&tile[v][i][j].flags, sizeof(dword), 1, fin);
           fread(&tile[v][i][j].alpha, sizeof(byte), 1, fin);
   }

   fclose(fin);
   
   ResetTimers();
   delete[] temp;
   return 0;
}


int CMap::SaveMap(std::string filename)
{
        FILE *fout = fopen( filename.c_str(), "wb");
        char *temp = new char[255];
        
        if(!fout) allegro_message("Error: Couldn't find map!");

        name = get_filename(filename.c_str());
        fputs("Name: ", fout);
        fputs(name.c_str(), fout);
        fputs("\n", fout);

        fputs("Tileset: ", fout);
		tileset_name = get_filename(tileset_name.c_str());
		tileset_name = "./data/" + tileset_name;
        fputs(tileset_name.c_str(), fout);
        fputs("\n", fout);

        fputs("Spriteset: ", fout);
		spriteset_name = get_filename(spriteset_name.c_str());
		spriteset_name = "./data/" + spriteset_name;
        fputs(spriteset_name.c_str(), fout);
        fputs("\n", fout);

        fwrite(&w, sizeof(dword), 1, fout);
        fwrite(&h, sizeof(dword), 1, fout);
        fwrite(&layers, sizeof(byte), 1, fout);

        fwrite(&sizew, sizeof(int), 1, fout);
        fwrite(&sizeh, sizeof(int), 1, fout);
		
		fwrite(&config, sizeof(int), 1, fout);

      	fwrite(&isbattle, sizeof(bool), 1, fout);
      	fwrite(&cine_id, sizeof(int), 1, fout);
     	fwrite(&player_start_x, sizeof(dword), 1, fout);
    	fwrite(&player_start_y, sizeof(dword), 1, fout);
     	
     	fwrite(&player1_start_x, sizeof(dword), 1, fout);
    	fwrite(&player1_start_y, sizeof(dword), 1, fout);

		char name_holder[1024];

/*
        for(int j = 0; j<255; ++j) name_holder[j] = ' ';
		strcpy( name_holder, battle_destmap.c_str());
      	fwrite(name_holder,1,255, fout);
*/
        fputs("\n", fout);
        fputs("BDestmap: ", fout);
        battle_destmap = get_filename(battle_destmap.c_str());
        battle_destmap = "./data/" + battle_destmap;
        fputs(battle_destmap.c_str(), fout);
        fputs("\n", fout);

//allegro_message("%s saving " , name_holder);
   		fwrite(&battle_x, sizeof(dword), 1, fout);
       	fwrite(&battle_y, sizeof(dword), 1, fout);
       	
		fwrite(&max_portal, sizeof(dword), 1, fout);
		for(dword i = 0; i < max_portal; ++i)
        {
			fwrite(&portal[i].srcx, sizeof(dword), 1, fout);
			fwrite(&portal[i].srcy, sizeof(dword), 1, fout);
			fwrite(&portal[i].destx, sizeof(dword), 1, fout);
			fwrite(&portal[i].desty, sizeof(dword), 1, fout);
			fwrite(&portal[i].cine_id, sizeof(dword), 1, fout);
    		fwrite(&portal[i].check_quest, sizeof(dword), 1, fout);
	        for(int j = 0; j<255; ++j) name_holder[j] = ' ';
            strcpy( name_holder, portal[i].name.c_str());
          
           	fwrite(name_holder,1,255, fout);
		}
		
		fwrite(&max_event, sizeof(dword), 1, fout);
		for(dword i = 0; i < max_event; ++i)
		{
			fwrite(&event[i].x, sizeof(dword), 1, fout);
			fwrite(&event[i].y, sizeof(dword), 1, fout);
			fwrite(&event[i].flags, sizeof(dword), 1, fout);
    		fwrite(&event[i].id, sizeof(int), 1, fout);
	        for(int j = 0; j<255; ++j) name_holder[j] = ' ';
            strcpy( name_holder, event[i].name.c_str());
         	fwrite(name_holder,1,255, fout);
	        for(int j = 0; j<1024; ++j) name_holder[j] = ' ';
            strcpy( name_holder, event[i].text.c_str());
         	fwrite(name_holder,1,1024, fout);
        	for(int j = 0; j<1024; ++j) name_holder[j] = ' ';
            strcpy( name_holder, event[i].posttext.c_str());
         	fwrite(name_holder,1,1024, fout);
		}

		fwrite(&max_npc, sizeof(dword), 1, fout);
		for(dword i = 0; i < max_npc; ++i)
		{
			fwrite(&npc[i].x, sizeof(dword), 1, fout);
			fwrite(&npc[i].y, sizeof(dword), 1, fout);
			fwrite(&npc[i].flags, sizeof(dword), 1, fout);
			fwrite(&npc[i].gfx, sizeof(byte), 1, fout);
         	fwrite(&npc[i].id, sizeof(int), 1, fout);
		}

for(dword v=0; v<tile.size(); v++)			// layer
 for(dword i=0; i<tile[0].size(); i++)		      // y(height)
   for(dword j=0; j<tile[0][0].size(); j++)		// x(width)
   {
           fwrite(&tile[v][i][j].gfx, sizeof(dword), 1, fout);
           fwrite(&tile[v][i][j].flags, sizeof(dword), 1, fout);
           fwrite(&tile[v][i][j].alpha, sizeof(byte),  1, fout);
   }

        delete[] temp;
        fclose(fout);
        return 0;
}


// Sets everything to defaults, just in case
void CMap::InitMap(dword width, dword height, int tilesizex, int tilesizey, dword layers)
{

        /* Name */
                //name = "NULL";
                //tileset_name = "NULL";
//		spriteset_name = "NULL";

        /* Width */
                w = width;
				
        /* Height */
                h = height;
				
        /* Layers */
                this->layers = layers;
				
        /* Tile Width and Tile Height */
				sizew = tilesizex;
				sizeh = tilesizey;
				
				bltx = (screen->w/sizew)+1;
				blty = (screen->h/sizeh)+1;

        ResizeMap();

for(dword v=0; v<tile.size(); v++)			// layer
 for(dword i=0; i<tile[0].size(); i++)		        // y(height)
   for(dword j=0; j<tile[0][0].size(); j++)		// x(width)
   {
            tile[v][i][j].gfx = 0;
            tile[v][i][j].flags = 0;
            tile[v][i][j].alpha = 0;
   }
   




}

// TODO: Optimize! Check Bob's website if there's a better way to do those break's
void CMap::DrawMap(byte layer, dword mapdrawx, dword mapdrawy)
{
   dword mapx, mapy;
   dword map_xo, map_yo;

   mapx = mapdrawx  / sizew;
   mapy = mapdrawy  / sizeh;

   map_xo = mapdrawx % sizew;
   map_yo = mapdrawy % sizeh;

  for(int i = 0; i < blty; i++)
  {
	if( i >= h ) break;
   for(int j = 0; j < bltx; j++)
    {
		if( j >= w ) break;
		DrawTile(tile[layer][mapy+i][mapx+j].gfx, j*sizew-map_xo, i*sizeh-map_yo);
		DrawTileTrans(tile[1][mapy+i][mapx+j].gfx, j*sizew-map_xo, i*sizeh-map_yo);
    }
  }

}

void CMap::DrawMapTrans(byte layer, dword mapdrawx, dword mapdrawy)
{
   dword mapx, mapy;
   dword map_xo, map_yo;

   mapx = mapdrawx  / sizew;
   mapy = mapdrawy  / sizeh;

   map_xo = mapdrawx % sizew;
   map_yo = mapdrawy % sizeh;

  for(int i = 0; i < blty; i++)
  {
	if( i >= h ) break;

   for(int j = 0; j < bltx; j++)
    {
		if( j >= w ) break;
		DrawTileTrans(tile[layer][mapy+i][mapx+j].gfx, j*sizew-map_xo, i*sizeh-map_yo);
    }
  }

}
void CMap::TransTileGfx(dword loc, int x, int y)
{
//	int xtile = 0;
//	int ytile = 0;

//	xtile=(loc-1) % (tile_bmp->w/sizew);
//	ytile=(loc-1) / (tile_bmp->h/sizeh);

//	blit(tile_bmp, Display.GetSurface(), xtile*sizew, ytile*sizeh, x, y, sizew, sizeh);
if(loc != 0)
    fblend_rect_trans(Display.GetSurface(), x, y, map.sizew, map.sizeh, makecol(255,0,0), 150 );
}

void CMap::TransTile(int hit, dword mapdrawx, dword mapdrawy)
{
   dword mapx, mapy;
   dword map_xo, map_yo;

   mapx = mapdrawx  / sizew;
   mapy = mapdrawy  / sizeh;

   map_xo = mapdrawx % sizew;
   map_yo = mapdrawy % sizeh;

  for(int i = 0; i < blty; i++)
  {
	if( i > h ) break;
   for(int j = 0; j < bltx; j++)
    {
		if( j > w ) break;
//		DrawTileTrans(tile[layer][mapy+i][mapx+j].gfx, j*sizew-map_xo, i*sizeh-map_yo);
       TransTileGfx(hit,  j*sizew-map_xo, i*sizeh-map_yo);

    }
  }

}
/*
void CMap::DrawTile(dword loc, int x, int y)
{
	int xtile = 0;
	int ytile = 0;

	xtile=(loc-1) % (tile_bmp->w/sizew);
	ytile=(loc-1) / (tile_bmp->h/sizeh);

	blit(tile_bmp, Display.GetSurface(), xtile*sizew, ytile*sizeh, x, y, sizew, sizeh);
}
*/
void CMap::DrawMapEditor(byte layer, dword mapdrawx, dword mapdrawy)
{
   dword mapx, mapy;
   dword map_xo, map_yo;

   mapx = mapdrawx  / sizew;
   mapy = mapdrawy  / sizeh;

   map_xo = mapdrawx % sizew;
   map_yo = mapdrawy % sizeh;

  for(int i = 0; i < blty; i++)
  {
	if( i >= h ) break;
   for(int j = 0; j < bltx; j++)
    {
		if( j >= w ) break;
		DrawTile(tile[layer][mapy+i][mapx+j].gfx, j*sizew-map_xo, i*sizeh-map_yo);
		
		if(CHECK_BIT(tile[layer][mapy+i][mapx+j].flags, FLAG_WALKABLE))
		{
			line(Display.GetSurface(), j*sizew-map_xo, i*sizeh-map_yo,  j*sizew-map_xo+sizew, i*sizeh-map_yo+16, makecol(255,0,0) );
			line(Display.GetSurface(), j*sizew-map_xo, i*sizeh-map_yo+16,  j*sizew-map_xo+sizew, i*sizeh-map_yo, makecol(255,0,0) );
		}
		
		if(CHECK_BIT(tile[LAYER_EVENT][mapy+i][mapx+j].flags, FLAG_EVENT) && layer == LAYER_EVENT)
		{
          for(int d = 0; d<max_event; ++d)
          {
             if(event[d].flags == EVENT_MSG && event[d].y == mapy+i && event[d].x == mapx+j)// && event[i].x == j-mapx && event[i].y == i-mapy )
                textprintf(Display.GetSurface(), font, j*sizew-map_xo, i*sizeh-map_yo, makecol(255,0,0), "M");
//              textprintf(Display.GetSurface(), font, j*sizew-mapx*sizew, i*sizeh+sizeh-mapy*sizeh-sizeh, makecol(255,0,0), "M");

             else if(event[d].flags == EVENT_SIGN && event[d].y == mapy+i && event[d].x == mapx+j)// && event[i].x == j-mapx && event[i].y == i-mapy )
                textprintf(Display.GetSurface(), font, j*sizew-map_xo, i*sizeh-map_yo, makecol(255,0,0), "S");
          //    textprintf(Display.GetSurface(), font, j*sizew-mapx*sizew, i*sizeh+sizeh-mapy*sizeh-sizeh, makecol(255,0,0), "S");
          
             else if(event[d].flags == EVENT_SHOP_WEAPON && event[d].y == mapy+i && event[d].x == mapx+j)
                 textprintf(Display.GetSurface(), font, j*sizew-map_xo, i*sizeh-map_yo, makecol(255,0,0), "SH");
          }
		}
		
		if(CHECK_BIT(tile[layer][mapy+i][mapx+j].flags, FLAG_PORTAL) && layer == LAYER_GROUND)
		{
			line(Display.GetSurface(), j*sizew-map_xo, i*sizeh-map_yo+8, j*sizew-map_xo+16,i*sizeh-map_yo+8, makecol(255,0,0) );
		}

     	if(CHECK_BIT(tile[layer][mapy+i][mapx+j].flags, FLAG_WAYPOINT) && layer == LAYER_GROUND)
		{
           textprintf(Display.GetSurface(), font, j*sizew-map_xo, i*sizeh-map_yo, makecol(255,0,0), ".");
		}

		if(  mapy+i == player_start_y && mapx+j == player_start_x)
		{
           textprintf(Display.GetSurface(), font, j*sizew-map_xo, i*sizeh-map_yo, makecol(255,0,0), "P0");
        }
        
        if(  mapy+i == player1_start_y && mapx+j == player1_start_x)
		{
           textprintf(Display.GetSurface(), font, j*sizew-map_xo, i*sizeh-map_yo, makecol(255,0,0), "P1");
        }

    }
  }

}

void CMap::DrawTile(dword loc, int x, int y)
{
	int xtile = 0;
	int ytile = 0;

	xtile=(loc-1) % (tile_bmp->w/sizew);
	ytile=(loc-1) / (tile_bmp->h/sizeh);

	blit(tile_bmp, Display.GetSurface(), xtile*sizew, ytile*sizeh, x, y, sizew, sizeh);
}

void CMap::DrawTileTrans(dword loc, int x, int y)
{

if(loc != 0) // Hey it's either this or draw a bunch of empty tiles
{
	int xtile = 0;
	int ytile = 0;
	xtile=(loc-1) % (tile_bmp->w/sizew);
	ytile=(loc-1) / (tile_bmp->h/sizeh);

	masked_blit(tile_bmp, Display.GetSurface(), xtile*sizew, ytile*sizeh, x, y, sizew, sizeh);
}
}

// TODO: Fix this -- It draws all objects in the map regardless of whether or not they're visible!
void CMap::DrawObjects(byte layer, dword mapdrawx, dword mapdrawy)
{
   dword mapx, mapy;
   dword map_xo, map_yo;

   mapx = mapdrawx  / sizew;
   mapy = mapdrawy  / sizeh;

   map_xo = mapdrawx % sizew;
   map_yo = mapdrawy % sizeh;

//  for(int i = 0; i<max_npc; ++i)
  {
     for(int i = 0; i<max_npc; ++i)
         masked_blit( sprite_bmp, Display.GetSurface(), npc[i].frame*16, npc[i].gfx*sizeh,
                 map.npc[i].x-mapdrawx, map.npc[i].y-mapdrawy, sizew, sizeh);
//	  rect(Display.GetSurface(), map.npc[i].x-mapdrawx, map.npc[i].y-mapdrawy, (map.npc[i].x+16-1)-mapdrawx, (map.npc[i].y+16-1)-mapdrawy, makecol(255,255,255));
  }
  /*
  for(int i = 0; i < blty; i++)
  {
	if( i > h ) break;
   for(int j = 0; j < bltx; j++)
    {
		if( j > w ) break;
		DrawTile(tile[layer][mapy+i][mapx+j].gfx, j*sizew-map_xo, i*sizeh-map_yo);
    }
  }
  */
}

void CMap::LoadTileset(std::string filename)
{
	tile_bmp = load_bitmap((filename.c_str()), NULL);
	tileset_name = get_filename(filename.c_str());
	if(!tile_bmp) allegro_message("Warning: Tileset could not be found! '%s'  ", get_filename(filename.c_str()));
}

void CMap::LoadSpriteset(std::string filename)
{
	sprite_bmp = load_bitmap(filename.c_str(), NULL);
	spriteset_name = get_filename(filename.c_str());
	if(!sprite_bmp) allegro_message("Warning: Spriteset could not be found! '%s'  ", get_filename(filename.c_str()));
}


bool CMap::Collision(dword x, dword y)
{
	return CHECK_BIT(tile[0][y/sizeh][x/sizew].flags, FLAG_WALKABLE);
}


void Move(int &x, int &y, int dir)
{
	x++;
}


void CMap::CheckEvents(CPlayer &pc)
{
	for(int i = 0; i<max_event; ++i)
	{
		if((event[i].x == pc.x/16 && event[i].y == pc.y/16) 		||
		   (event[i].x == (pc.x+15)/16 && event[i].y == pc.y/16) 	||
		   (event[i].x == (pc.x)/16 && event[i].y == (pc.y+15)/16)  ||
		   (event[i].x == (pc.x+15)/16 && event[i].y == (pc.y+15)/16) )
		   { 
			   if( CHECK_BIT(event[i].flags, EVENT_MSG) && event[i].read == false )
			   {
				   Talk(event[i].name, event[i].text); event[i].read = true;
                   if(event[i].id != 0) quest.ProcessQuest(event[i].id);
			   }
//			   else return true;
		   }	
	}
//	return false;
}

// CheckPortals
// Checks for the portals on the flags level... **Assumes all portal flags are on the ground layer (0)
void CMap::CheckPortals(CPlayer &pc)
{
     /*
if( CHECK_BIT( tile[0][player[0].y/sizeh][player[0].x/sizew].flags, FLAG_PORTAL) )
{
    allegro_message("HIT");
*/

//}

	for(int i = 0; i<max_portal; ++i)
	{
/*		if((portal[i].srcx/16 == pc.x/16 && portal[i].srcy/16 == pc.y/16) 		||
		   (portal[i].srcx/16 == (pc.x+15)/16 && portal[i].srcy/16 == pc.y/16) 	||
		   (portal[i].srcx/16 == (pc.x)/16 && (portal[i].srcy)/16 == (pc.y+15)/16)  ||
		   (portal[i].srcx/16 == (pc.x+15)/16 && (portal[i].srcy)/16 == (pc.y+15)/16) )
*/

		if( pc.x+map.sizew > portal[i].srcx &&
      		pc.y+map.sizeh > portal[i].srcy  &&
			pc.x < portal[i].srcx + map.sizew  &&
			pc.y < portal[i].srcy + map.sizeh )


	
		   {
             std::string temp_mapname = get_filename(map.name.c_str());
             std::string orig_portal_name = get_filename(portal[i].name.c_str());

if(CHECK_BIT(quest.quest_bit,portal[i].check_quest) || portal[i].check_quest == 0)
{
             pc.x = portal[i].destx;
             pc.y = portal[i].desty;
             int srcx = portal[i].srcx;
             int srcy = portal[i].srcy;
			 map.LoadMap(portal[i].name);

             map.CheckCine();

             if(portal[i].cine_id != 0)
             {
                cine.BeginCine(portal[i].cine_id);
                LoadMap("./data/"+temp_mapname);
             }
                map.LoadMap("./data/"+orig_portal_name);
                LoadNpcs();

                pc.UpdateMovement(); // update camera;
   if(map.CheckBattle())
   {
             // Check if you've fought the battle already..
              bool neverfought = true;
              for(int j = 0; j<player[0].max_battles; ++j)
              {
                if( player[0].fought_battles[j] == orig_portal_name)
                {
                  neverfought = false;
                  //allegro_message("%s", player[0].fought_battles[j].c_str());
                }
              }

             if(neverfought)
             {
                for(int j = 0; j<player[0].max_battles; ++j)
                {
                  if(player[0].fought_battles[j] == "empty")
                  {
                     player[0].fought_battles[j] = orig_portal_name;
                     break;
                  }
                }

                battle.Battle(true);
                LoadMap("./data/"+temp_mapname); // reverts back to orig map
                LoadNpcs();
                player[0].x = srcx;
                player[0].y = srcy;
                player[0].UpdateMovement();
             }
             
             if(!neverfought)
             {
                LoadMap("./data/"+temp_mapname); // reverts back to orig map
                LoadNpcs();
               // allegro_message("%d", map.max_portal);
                player[0].x = srcx;
                player[0].y = srcy;
                player[0].UpdateMovement();
             for(int revamp = 0; revamp < map.max_portal; ++revamp)
             {
              if(map.portal[revamp].srcx == srcx && map.portal[revamp].srcy == srcy)
              {
                std::vector<CPortal>::iterator pos;
                pos = map.portal.begin() + revamp;
                map.portal.erase(pos);
                map.max_portal--;
                  // allegro_message("%d %d %d", map.max_portal, map.portal[0].srcx, map.portal[1].srcx);
              }
             }
            //    REMOVE_BIT(map.tile[0][srcy/16][srcx/16].flags, FLAG_PORTAL);
             }
             
    }
    
    
    
    
       /*Clear the kbbuffer! */
       remove_keyboard();
       install_keyboard();
       ResetTimers();
}
           

//             key[KEY_RIGHT] = 0;
		   }
	}

    

}


// Collision detection for NPCs
bool CMap::CheckNpcs(int x, int y)
{
	for(int i = 0; i<max_npc; ++i)
	{

		if( x+map.sizew >  npc[i].x &&
      		y + map.sizeh > npc[i].y  &&
			x < npc[i].x + map.sizew  &&
			y < npc[i].y+map.sizeh )
		   {
				return true;

		   }
	}
	
	return false;
}

// TODO: shouldn't use 16 ... use player[0].width (once implemented)
// TODO: cleanup -- two if checks shouldn't be necessary!!!
bool CMap::CheckPlayer(int x, int y)
{
/*
     allegro_message("x+16 = %d > playerx %d", x+16, player[0].x);
     allegro_message("y+16 = %d > playery %d", y+16, player[0].y);
     allegro_message("x %d < playerx + 16 %d", x, player[0].x+16);
     allegro_message("y %d < player[0].y + 16 %d", y, player[0].y+16);
*/
        if( x+16 >  player[0].x &&
      		y + 16 > player[0].y  &&
			x < player[0].x + 16 &&  //
			y < player[0].y + 16 )    //
		   {
				return true;
		   }
		   
        if( x+16 >  player[1].x &&
      		y + 16 > player[1].y  &&
			x < player[1].x + 16  &&
			y < player[1].y + 16 )
		   {
				return true;
		   }
		   
  return false;
}

int CMap::WhichPlayer(int x, int y)
{
  if( x+16 >  player[0].x &&
      y + 16 > player[0].y  &&
	  x < player[0].x + 16 &&
	  y < player[0].y + 16 )
	  {
	    	return 0;
	  }
	  
   if( x+16 >  player[1].x &&
       y + 16 > player[1].y  &&
	   x < player[1].x + 16  &&
	   y < player[1].y + 16 )
	  {
			return 1;
	  }

    return -1;
}
void CMap::InteractNpcs(int x, int y)
{
	for(int i = 0; i<max_npc; ++i)
	{

		if( x+ map.sizew >  npc[i].x &&
      		y + map.sizeh > npc[i].y  &&
			x < npc[i].x + map.sizew  &&
			y < npc[i].y+map.sizeh )
		   {
           if(npc[i].id-1 >= 0) // if the id-1 is less than 0 then the NPC doesn't talk
           {
             if(npcinfo[npc[i].id-1].yesno == "none" && !CHECK_BIT(quest.quest_bit, npcinfo[npc[i].id-1].quest_idnum))
              Talk(npcinfo[npc[i].id-1].name, npcinfo[npc[i].id-1].text);

             else if(CHECK_BIT(quest.quest_bit, npcinfo[npc[i].id-1].quest_idnum) && npcinfo[npc[i].id-1].yesno == "none")
             {
                Talk(npcinfo[npc[i].id-1].name, npcinfo[npc[i].id-1].quest_text);
             }
              
             else if(npcinfo[npc[i].id-1].yesno == "yesno")
              {
               if(CHECK_BIT(quest.quest_bit, npcinfo[npc[i].id-1].quest_idnum))
               {
                   Talk(npcinfo[npc[i].id-1].name, npcinfo[npc[i].id-1].quest_text);
               }
               else if( menu.Choice(Talk(npcinfo[npc[i].id-1].name, npcinfo[npc[i].id-1].text, 1)) )
               {

                   Talk(npcinfo[npc[i].id-1].name, npcinfo[npc[i].id-1].yestext);
                   quest.ProcessQuest(npcinfo[npc[i].id-1].quest_idnum);

               }

               else
               {
                   Talk(npcinfo[npc[i].id-1].name, npcinfo[npc[i].id-1].notext);
               }
             }
             
//allegro_message("%d", npcinfo[npc[i].id-1].quest_idnum);
             // This checks for a quest being completed and then sets another quest
             if(npcinfo[npc[i].id-1].yesno == "setcheckquest" && !CHECK_BIT(quest.quest_bit, npcinfo[npc[i].id-1].quest_idnum) )
                 Talk(npcinfo[npc[i].id-1].name, npcinfo[npc[i].id-1].text);

             else if(CHECK_BIT(quest.quest_bit, npcinfo[npc[i].id-1].quest_idnum) && npcinfo[npc[i].id-1].yesno == "setcheckquest")
             {
                Talk(npcinfo[npc[i].id-1].name, npcinfo[npc[i].id-1].quest_text);
                quest.ProcessQuest(npcinfo[npc[i].id-1].set_quest_idnum);
             }


             if(npcinfo[npc[i].id-1].yesno == "checkquest") //&& !CHECK_BIT(quest.quest_bit, npcinfo[npc[i].id-1].quest_idnum) )
             {
                 quest.ProcessQuest(npcinfo[npc[i].id-1].quest_idnum);
                 
                 if(CHECK_BIT(quest.quest_bit, npcinfo[npc[i].id-1].quest_idnum) )
                    Talk(npcinfo[npc[i].id-1].name, npcinfo[npc[i].id-1].quest_text);
                 else
                    Talk(npcinfo[npc[i].id-1].name, npcinfo[npc[i].id-1].text);
             }
             
             if(npcinfo[npc[i].id-1].yesno == "setquest")
             {
                SET_BIT(quest.quest_bit, npcinfo[npc[i].id-1].quest_idnum);
                Talk(npcinfo[npc[i].id-1].name, npcinfo[npc[i].id-1].text);
             }
             
             if(npcinfo[npc[i].id-1].yesno == "procquest")
             {
                quest.ProcessQuest(npcinfo[npc[i].id-1].set_quest_idnum);
                Talk(npcinfo[npc[i].id-1].name, npcinfo[npc[i].id-1].text);
             }
             /* // TODO: Add a setquest and checkquest bit in npcs.txt
     
             if(npcinfo[npc[i].id-1].quest_idnum != 0 && CHECK_BIT(quest.quest_bit, npcinfo[npc[i].id-1].quest_idnum)
                && npcinfo[npc[i].id-1].yesno == "none")
             {
               quest.ProcessQuest(npcinfo[npc[i].id-1].quest_idnum);
             }
             */
           }
		   }
	}
}
     

// CEvent -- See CMap.hpp for def
CEvent::CEvent()
{
	read = false;
    id = 0;
    name = "";
    posttext = "";
    text = "";
}


using namespace std;
void CMap::LoadNpcs()
{
    std::ifstream fin;
    fin.open("./data/npcs.txt");
    char temp[1024];
    
    npcinfo.resize(1);

    int counter = 0;
    while(!fin.eof())
    {
  //   fin >> npcinfo[counter].id;
     for(int i = 0; i < 1024; ++i)
               temp[i] = ' ';
     fin.getline( temp, 255);
     npcinfo[counter].id = atol(temp);

     for(int i = 0; i < 1024; ++i)
             temp[i] = ' ';
     fin.getline( temp, 255);
       npcinfo[counter].name = temp;

     for(int i = 0; i < 1024; ++i)
             temp[i] = ' ';
     fin.getline( temp, 1024);
        npcinfo[counter].text = temp;

     for(int i = 0; i < 1024; ++i)
             temp[i] = ' ';
     fin.getline( temp, 1024);
        npcinfo[counter].yesno = temp;

     for(int i = 0; i < 1024; ++i)
             temp[i] = ' ';
     fin.getline( temp, 1024);
        npcinfo[counter].yestext = temp;
        
     for(int i = 0; i < 1024; ++i)
             temp[i] = ' ';
     fin.getline( temp, 1024);
        npcinfo[counter].notext = temp;

     for(int i = 0; i < 1024; ++i)
             temp[i] = ' ';
     fin.getline( temp, 1024);
        npcinfo[counter].quest_idnum = atol(temp);
        
     for(int i = 0; i < 1024; ++i)
             temp[i] = ' ';
     fin.getline( temp, 1024);
        npcinfo[counter].set_quest_idnum = atol(temp);

     for(int i = 0; i < 1024; ++i)
             temp[i] = ' ';
     fin.getline( temp, 1024);
        npcinfo[counter].quest_text = temp;
        
        
     
     npcinfo.resize(npcinfo.size()+1);
     ++counter;
    }
    fin.close();
}

int CMap::GetNpcid(int x, int y)
{

     for(int i = 0; i<max_npc; ++i)
     {
       if(x == npc[i].x && y == npc[i].y)
       {
         return i;
       }
     }
     
     return 0;
}

void CMap::RenderScene(int x, int y)
{
    map.DrawMap(0, x, y); // Walls
	map.DrawMapTrans(1, x, y); // Overlap
    map.DrawObjects( NULL, x, y);
   // masked_blit( player[0].gfx, Display.GetSurface(), player[0].frame*16, player[0].facing*16, player[0].x-x, player[0].y-y, 16, 16);
}


void CMap::CheckCine()
{
   if(cine_id != 0)
   {
     cine.BeginCine(cine_id);
   }
}

bool CMap::CheckBattle()
{
     return isbattle;
}

void CMap::SetPositions()
{
     player[0].x = player_start_x*sizew;
     player[0].y = player_start_y*sizeh;

     player[1].x = player1_start_x*sizew;
     player[1].y = player1_start_y*sizeh;
}
