#include "allegro.h"
//#include "CObject.h"
#include "CTileSet.h"

#ifndef CMap_def

#define CMap_def

//the heigth and width of the map
#define mw  200
#define mh  200
//#define max_objects 50


class CMap
{
private:
    CTile *tile[mw][mh];

    CTile *layer2[mw][mh];

public:
    //fill the map with the given tile
    void init(CTile *tTemp);
    //adds the given tile number from the given tileset at the pos_x,pos_y
    void add_tile(CTileSet *TileSet, int tile_num, int pos_x, int pos_y, int layer);
    //draws the map starting with the top left corner at s_x, s_y
    void draw_map(BITMAP *backgr, float s_x, float s_y);
    //draws the map with a coloured-coded grid
    void draw_grid(BITMAP *backgr, float s_x, float s_y);
    //retuns the type of the tile at the world position of x,y
    int return_tile_status(float x, float y);
    //saves the map to the given filename
    void save_map(char *filename,CMapObjects *objects);
    //loads the map using the given tileset, the given blank tile, and the given datafile
    void load_map(char *filename, CTileSet *ts, CTile *blank, DATAFILE *d, CObjectSet *os, CMapObjects *objects);
    void destroy_map(void);
    void del_tile (CTile *tTemp, int x, int y, int layer);
    void move_enim(void);

    void clean_up_all(DATAFILE *d, CTileSet *ts, int layer);

    void clean_up_tile(int x, int y, DATAFILE *d, CTileSet *ts);
    void clean_up2(int x, int y, DATAFILE *d, CTileSet *ts);

    void clean_up_tile_l2(int x, int y, DATAFILE *d, CTileSet *ts);
    void clean_up2_l2(int x, int y, DATAFILE *d, CTileSet *ts);

    int return_tile_num(int x, int y);

    void clean_up_box(DATAFILE *d, CTileSet *ts, float x1, float y1, float x2, float y2, int layer);

    void draw_layer2(BITMAP *backgr, float s_x, float s_y);
};

int CMap::return_tile_num(int x, int y)
{
    int ret=-1;
    if(x>0 & y>0)
        {
        ret = tile[x][y]->iTNum;
        }
    return ret;
}


void CMap::clean_up_box(DATAFILE *d, CTileSet *ts, float x1, float y1, float x2, float y2, int layer)
{
    float temp;

  /*  if(x2 < x1)
        {
        temp=x1;
        x1=x2;
        x2=temp;
        }
    if(y2 < y1)
        {
        temp=y1;
        y1=y2;
        y2=temp;
        }        */

    if (x1<x2 && y1<y2)
        {


    for(int x=(int)(x1/32) ; x <(int)(x2/32) ; x++)
        {
        for(int y=(int)(y1/32) ; y <(int)(y2/32) ; y++)
            {
            if(layer==1)
                clean_up_tile(x,y,d,ts);
            else if(layer==2)
                clean_up_tile_l2(x,y,d,ts);
            }
        }

    for(int x=(int)(x1/32) ; x <(int)(x2/32) ; x++)
        {
        for(int y=(int)(y1/32) ; y <(int)(y2/32) ; y++)
            {
            if(layer==1)
                clean_up2(x,y,d,ts);
            else if(layer==2)
                clean_up2_l2(x,y,d,ts);
            }
        }
        }
}

void CMap::clean_up_all(DATAFILE *d, CTileSet *ts, int layer)
{
    for(int x=0 ; x<mw-1 ; x++)
        {
        for(int y=0 ; y<mh-1 ; y++)
            {
            if(layer==1)
                clean_up_tile(x,y,d,ts);
            else if(layer==2)
                clean_up_tile_l2(x,y,d,ts);
            }
        }

    for(int x=0 ; x<mw-1 ; x++)
        {
        for(int y=0 ; y<mh-1 ; y++)
            {
            if(layer==1)
                clean_up2(x,y,d,ts);
            else if(layer==2)
                clean_up2_l2(x,y,d,ts);
            }
        }
}

void CMap::clean_up_tile(int xx, int yy,DATAFILE *d, CTileSet *ts)
{
    int temp;
    if(xx>0 && yy>0 && tile[xx][yy]->iPicNum!=-1 && tile[xx][yy]->iPicNum!=1)
        {
        tile[xx][yy]=ts->return_tile(3);

        if(yy>0) //cant be at the edge of the map
            {

            if(tile[xx][yy-1]->iPicNum==-1)
                tile[xx][yy]=ts->return_tile(2);
            }

        if( tile[xx+1][yy]->iPicNum == -1)
            {
            if(tile[xx][yy]->iPicNum==2)
                tile[xx][yy]=ts->return_tile(4);
            else
                tile[xx][yy]=ts->return_tile(6);
            }

        if(xx>0)
            {
            if(tile[xx-1][yy]->iPicNum==-1)
                {
                if(tile[xx][yy]->iPicNum==2)
                    {
                    tile[xx][yy]=ts->return_tile(5);
                    }
                else
                    {
                    tile[xx][yy]=ts->return_tile(7);
                    }
                }
            }


/*************************************************/

        if(yy>0) //cant be at the edge of the map
            {

            if(layer2[xx][yy-1]->iPicNum==-1)
                tile[xx][yy]=ts->return_tile(2);
            }

        if( layer2[xx+1][yy]->iPicNum == -1)
            {
            if(tile[xx][yy]->iPicNum==2)
                tile[xx][yy]=ts->return_tile(4);
            else
                tile[xx][yy]=ts->return_tile(6);
            }

        if(xx>0)
            {
            if(layer2[xx-1][yy]->iPicNum==-1)
                {
                if(tile[xx][yy]->iPicNum==2)
                    {
                    tile[xx][yy]=ts->return_tile(5);
                    }
                else
                    {
                    tile[xx][yy]=ts->return_tile(7);
                    }
                }
            }
/*****************************************************************/


        }

}

void CMap::clean_up2(int xx, int yy, DATAFILE *d, CTileSet *ts)
{
    if(xx>0 && yy>0 && tile[xx][yy]->iPicNum!=-1 && tile[xx][yy]->iPicNum!=1)
        {
        //the tile is not grass-topped
        if(tile[xx][yy]->iPicNum==3 || tile[xx][yy]->iPicNum==6 || tile[xx][yy]->iPicNum==7)
            {

            if(xx>0)
                {
                    if(tile[xx-1][yy]->iPicNum==1)  //there is a come-from below next to it
                        tile[xx][yy]=ts->return_tile(8);
                }
            if(tile[xx+1][yy]->iPicNum==1)
                tile[xx][yy]=ts->return_tile(9);

            }
        else if(tile[xx][yy]->iPicNum==2 || tile[xx][yy]->iPicNum==4 || tile[xx][yy]->iPicNum==5)
            {

             if(xx>0)
                {
                    if(tile[xx-1][yy]->iPicNum==1)  //there is a come-from below next to it
                        tile[xx][yy]=ts->return_tile(10);
                }
            if(tile[xx+1][yy]->iPicNum==1)
                tile[xx][yy]=ts->return_tile(11);
            }

        if(xx>0 && yy>0)
            {
            if( (tile[xx-1][yy]->iPicNum==2 || tile[xx-1][yy]->iPicNum==5) &&  (tile[xx][yy-1]->iPicNum==7 || tile[xx][yy-1]->iPicNum==5))
                tile[xx][yy] = ts->return_tile(12);
            }
        if((tile[xx+1][yy]->iPicNum==2 || tile[xx-1][yy]->iPicNum==4) && (tile[xx][yy-1]->iPicNum==6 || tile[xx][yy-1]->iPicNum==4))
            tile[xx][yy] = ts->return_tile(13);

/*************************** */
//the tile is not grass-topped
        if(tile[xx][yy]->iPicNum==3 || tile[xx][yy]->iPicNum==6 || tile[xx][yy]->iPicNum==7)
            {

            if(xx>0)
                {
                    if(layer2[xx-1][yy]->iPicNum==1)  //there is a come-from below next to it
                        tile[xx][yy]=ts->return_tile(8);
                }
            if(layer2[xx+1][yy]->iPicNum==1)
                tile[xx][yy]=ts->return_tile(9);

            }
        else if(tile[xx][yy]->iPicNum==2 || tile[xx][yy]->iPicNum==4 || tile[xx][yy]->iPicNum==5)
            {

             if(xx>0)
                {
                    if(layer2[xx-1][yy]->iPicNum==1)  //there is a come-from below next to it
                        tile[xx][yy]=ts->return_tile(10);
                }
            if(layer2[xx+1][yy]->iPicNum==1)
                tile[xx][yy]=ts->return_tile(11);
            }

        if(xx>0 && yy>0)
            {
            if( (layer2[xx-1][yy]->iPicNum==2 || layer2[xx-1][yy]->iPicNum==5) &&  (layer2[xx][yy-1]->iPicNum==7 || layer2[xx][yy-1]->iPicNum==5))
                tile[xx][yy] = ts->return_tile(12);
            }
        if((layer2[xx+1][yy]->iPicNum==2 || layer2[xx-1][yy]->iPicNum==4) && (layer2[xx][yy-1]->iPicNum==6 || layer2[xx][yy-1]->iPicNum==4))
            tile[xx][yy] = ts->return_tile(13);
/********************************************/


        }
}

void CMap::clean_up_tile_l2(int xx, int yy,DATAFILE *d, CTileSet *ts)
{
    int temp;
    if(xx>0 && yy>0 && layer2[xx][yy]->iPicNum!=-1 && layer2[xx][yy]->iPicNum!=1)
        {
        layer2[xx][yy]=ts->return_tile(3);

        if(yy>0) //cant be at the edge of the map
            {
            //temp = yy-1;
            if(layer2[xx][yy-1]->iPicNum==-1)
                layer2[xx][yy]=ts->return_tile(2);
            }

        //temp=xx+1;

        if( layer2[xx+1][yy]->iPicNum == -1)
            {
            if(layer2[xx][yy]->iPicNum==2)
                layer2[xx][yy]=ts->return_tile(4);
            else
                layer2[xx][yy]=ts->return_tile(6);
            }

        if(xx>0)
            {
            if(layer2[xx-1][yy]->iPicNum==-1)
                {
                if(layer2[xx][yy]->iPicNum==2)
                    {
                    layer2[xx][yy]=ts->return_tile(5);
                    }
                else
                    {
                    layer2[xx][yy]=ts->return_tile(7);
                    }
                }
            }
       // tile[xx][yy]->set_picture(d,ts);
        //tile[xx][yy] = ts->return_tile(tile[xx][yy]->iPicNum);
        }

}

void CMap::clean_up2_l2(int xx, int yy, DATAFILE *d, CTileSet *ts)
{
    if(xx>0 && yy>0 && layer2[xx][yy]->iPicNum!=-1 && layer2[xx][yy]->iPicNum!=1)
        {
        //the tile is not grass-topped
        if(layer2[xx][yy]->iPicNum==3 || layer2[xx][yy]->iPicNum==6 || layer2[xx][yy]->iPicNum==7)
            {

            if(xx>0)
                {
                    if(layer2[xx-1][yy]->iPicNum==1)  //there is a come-from below next to it
                        layer2[xx][yy]=ts->return_tile(8);
                }
            if(layer2[xx+1][yy]->iPicNum==1)
                layer2[xx][yy]=ts->return_tile(9);

            }
        else if(layer2[xx][yy]->iPicNum==2 || layer2[xx][yy]->iPicNum==4 || layer2[xx][yy]->iPicNum==5)
            {

             if(xx>0)
                {
                    if(layer2[xx-1][yy]->iPicNum==1)  //there is a come-from below next to it
                        layer2[xx][yy]=ts->return_tile(10);
                }
            if(layer2[xx+1][yy]->iPicNum==1)
                layer2[xx][yy]=ts->return_tile(11);
            }

        if(xx>0 && yy>0)
            {
            if( (layer2[xx-1][yy]->iPicNum==2 || layer2[xx-1][yy]->iPicNum==5) &&  (layer2[xx][yy-1]->iPicNum==7 || layer2[xx][yy-1]->iPicNum==5))
                layer2[xx][yy] = ts->return_tile(12);
            }
        if((layer2[xx+1][yy]->iPicNum==2 || layer2[xx-1][yy]->iPicNum==4) && (layer2[xx][yy-1]->iPicNum==6 || layer2[xx][yy-1]->iPicNum==4))
            layer2[xx][yy] = ts->return_tile(13);

        }
}

void CMap::del_tile(CTile *tTemp, int x, int y, int layer)
{
    if(layer==1)
        tile[x][y]=tTemp;
    else if(layer==2)
        layer2[x][y]=tTemp;
}


void CMap::destroy_map(void)
{
   // for(int n=0 ; n<max_objects ; n++)
    //    object[n].destroy();
}

void CMap::save_map(char *filename, CMapObjects *objects)
{
    FILE *fp=fopen(filename,"w");

    objects->save_objects(fp);
  /*  fprintf(fp,"%d ",next_object);  //the total number of objects

    for(int n=0 ; n<next_object ; n++)
        {
        object[n].finalize_movement();
        fprintf(fp,"%d ",object[n].exist);
        fprintf(fp,"%d ",object[n].pic_num);
        if(object[n].pic_num==-1)
            fprintf(fp,"%s ",object[n].anim_file);
        fprintf(fp,"%d ",object[n].pickup_type);
        fprintf(fp,"%d ",object[n].type);
        fprintf(fp,"%f ",object[n].p1.x);
        fprintf(fp,"%f ",object[n].p1.y);
        fprintf(fp,"%f ",object[n].p2.x);
        fprintf(fp,"%f ",object[n].p2.y);
        }  */

    for(int x=0 ; x<mw ; x++)
        {
        for(int y=0 ; y<mh ; y++)
            {
            //tile[x][y]->save_tile(fp);
            fprintf(fp,"%d ",tile[x][y]->iPicNum);
            }
        }

    for(int x=0 ; x<mw ; x++)
        {
        for(int y=0 ; y<mh ; y++)
            {
            //tile[x][y]->save_tile(fp);
            fprintf(fp,"%d ",layer2[x][y]->iPicNum);
            }
        }
    fclose(fp);
}

void CMap::load_map(char *filename, CTileSet *ts, CTile *blank, DATAFILE *d, CObjectSet *os, CMapObjects *objects)
{
    int temp_exist,temp_pic_num;

    int iTemp;
    Point pTemp={0,0};
    FILE *fp=fopen(filename,"r");

    //objects->
    objects->load_objects(os, fp,d);

    for(int x=0 ; x<mw ; x++)
        {
        for(int y=0 ; y<mh ; y++)
            {
            //tile[x][y]=new tile
            //tile[x][y]->load_tile(fp,d);
            fscanf(fp,"%d ",&iTemp);
            if(iTemp!=-1)   //-1 is a blank tile
                {
                tile[x][y]=ts->return_tile(iTemp);
                tile[x][y]->iPicNum=iTemp;
                }
            else
                tile[x][y]=blank;
            }
        }

    for(int x=0 ; x<mw ; x++)
        {
        for(int y=0 ; y<mh ; y++)
            {
            //tile[x][y]=new tile
            //tile[x][y]->load_tile(fp,d);
            fscanf(fp,"%d ",&iTemp);
            if(iTemp!=-1)   //-1 is a blank tile
                {
                layer2[x][y]=ts->return_tile(iTemp);
                layer2[x][y]->iPicNum=iTemp;
                }
            else
                layer2[x][y]=blank;
            }
        }
    fclose(fp);

    //for(int n=0 ; n<next_object ; n++)
    //    object[n].create_anim();
}

int CMap::return_tile_status(float x, float y)
{
    int status=-1;
    int tx,ty,tx2,ty2;
    tx=(int)(x/32);
    ty=(int)(y/32);

    tx2=((int)x % 32);
    ty2=((int)y % 32);

    if(tile[tx][ty]->exist==true)
    if(tile[tx][ty]->iPicNum!=-1)    //must be a tile there
        {
        if((int)x%32 <tile[tx][ty]->pic->w && (int)y%32<tile[tx][ty]->pic->h)
            status=tile[tx][ty]->ret_status(tx2,ty2);
        }

    return status;
}



void CMap::draw_grid(BITMAP *backgr, float s_x, float s_y)
{
    int tilex_min=0,tiley_min=0, tilex_max=0, tiley_max=0;

    tilex_min = (int)(s_x/32);
    tiley_min = (int)(s_y/32);

    if(tilex_min<0)
        tilex_min=0;
    if(tiley_min<0)
        tiley_min=0;

    tilex_max = tilex_min + 20;
    tiley_max = tiley_min + 15;

    if(tilex_max > mw)
        tilex_max=mw;
    if(tiley_max > mh)
        tiley_max=mh;

    RGB col={255,255,255};
    RGB Red={255,0,0};
    RGB Lgreen={200,255,200};
    RGB Blue={0,0,255};
    RGB White={255,255,255};
    RGB DPurple={150,0,150};
   // int col=1;

    for(int x=tilex_min ; x<tilex_max+1 ; x++)
        for(int y=tiley_min ; y<tiley_max+1 ; y++)
        {
            tile[x][y]->draw_tile(backgr,-(x*32)+s_x , -(y*32)+s_y);

            if(tile[x][y]->ret_status()==0) //empty
                 col=Lgreen;
            else if(tile[x][y]->ret_status()==1) //normal tile
                 col=Blue;
            else if(tile[x][y]->ret_status()==2) //jump thru from below
                 col=DPurple;
            else
                col=White;

            rect(backgr,(int)((x*32)-s_x) , (int)((y*32)-s_y),(int)((x*32)-s_x+32)-1 , (int)((y*32)-s_y+32)-1, makecol(col.r , col.g , col.b) );
        }


}

void CMap::draw_map(BITMAP *backgr, float s_x, float s_y)
{
    int tilex_min=0,tiley_min=0, tilex_max=0, tiley_max=0;

    tilex_min = (int)(s_x/32);
    tiley_min = (int)(s_y/32);

    if(tilex_min<0)
        tilex_min=0;
    if(tiley_min<0)
        tiley_min=0;

    tilex_max = tilex_min + 20;
    tiley_max = tiley_min + 15;

    if(tilex_max > mw)
        tilex_max=mw;
    if(tiley_max > mh)
        tiley_max=mh;


    for(int x=tilex_min ; x<tilex_max+1 ; x++)
        for(int y=tiley_min ; y<tiley_max+1 ; y++)
        {
            tile[x][y]->draw_tile(backgr,-(x*32)+s_x , -(y*32)+s_y);
        }

}

void CMap::draw_layer2(BITMAP *backgr, float s_x, float s_y)
{
    int tilex_min=0,tiley_min=0, tilex_max=0, tiley_max=0;

    tilex_min = (int)(s_x/32);
    tiley_min = (int)(s_y/32);

    if(tilex_min<0)
        tilex_min=0;
    if(tiley_min<0)
        tiley_min=0;

    tilex_max = tilex_min + 20;
    tiley_max = tiley_min + 15;

    if(tilex_max > mw)
        tilex_max=mw;
    if(tiley_max > mh)
        tiley_max=mh;


    for(int x=tilex_min ; x<tilex_max+1 ; x++)
        for(int y=tiley_min ; y<tiley_max+1 ; y++)
        {
            layer2[x][y]->draw_tile(backgr,-(x*32)+s_x , -(y*32)+s_y);
        }

}


void CMap::add_tile(CTileSet *TileSet, int tile_num, int pos_x, int pos_y, int layer)
{
    if(pos_x < mw && pos_x >=0 && pos_y < mh && pos_y >=0)
    {
        if(layer==1)
            tile[pos_x][pos_y] = TileSet->return_tile(tile_num);
        else if(layer==2)
            layer2[pos_x][pos_y] = TileSet->return_tile(tile_num);
    }
}




void CMap::init(CTile *tTemp)
{
    //fills the tile array with empty tiles.
    for(int n1=0; n1<mw ; n1++)
        for(int n2=0; n2<mw ; n2++)
            {
            tile[n1][n2] = tTemp;
            layer2[n1][n2] = tTemp;
            }

}







#endif
