#include "cache.h"
#include <deque>

#define REAL_TILE_W  48
#define REAL_TILE_H  48

#define SCREEN_TILE_W  48
#define SCREEN_TILE_H  48

#define TILESET_WIDTH  12

#ifndef GAMEMAP_H_INCLUDED
#define GAMEMAP_H_INCLUDED



class MapFile {
  public:
    char name[64];
    int w, h;
    char back_1[128]; char back_2[128]; char back_3[128];
    char front_1[128]; char front_2[128]; char front_3[128];
    char tileset[128];
};

class SpawnPoint {
  public:
  int type, x, y;
  SpawnPoint(int tx, int ty, int t){x=tx; y=ty; type=t;}
  ~SpawnPoint(){}
};

class LightPoint {
  public:
    int type, x, y;
    LightPoint(int tx, int ty, int t){x=tx;y=ty;type=t;}
    void Draw();
    bool InsideScreen();
};



extern std::deque<LightPoint *> light_points;
extern std::deque<SpawnPoint *> spawn_points;

extern int MapPowers[];

class EditorStoryboard {
  public:
    std::string paragraph[8];
    float cam_x, cam_y;
    void clear() {
      for (int i=0;i!=8; i+=1) {
        paragraph[i].clear();
      }
      cam_x=cam_y=0;
    }
};

class MapStoryboard {
  public:
    char text[8][256];
    float cam_x, cam_y;
    void CopyFromEditor(EditorStoryboard *p);
    void Clear();
};

extern MapStoryboard actual_map_storyboard[];

class Map {
  protected:
    MapFile mf;
    CacheBitmap *tileset;
    CacheBitmap *back[3];
    CacheBitmap *front[3];
    short int **tiles[3];
    short int *collision_map;
    int w, h;
    float real_w, real_h;
    std::string name;
    std::string internal_name;
    bool weather;
  public:
    Map() {
      tileset = NULL;
      for (int i=0;i!=3;i+=1) {back[i]=NULL; front[i]=NULL;}
      w=h=0;
      name = "Map01";
      weather=false;
    }

    void Clear();

    int GetWeather() {return weather;}
    void SetWeather(int v) {weather=v;}

    void CopyToFile() {
      strcpy(mf.name, name.c_str());
      mf.w = w; mf.h = h;
      if (back[0] != NULL) strcpy(mf.back_1, back[0]->get_name().c_str());
      else strcpy(mf.back_1, "NONE");
      if (back[1] != NULL) strcpy(mf.back_2, back[1]->get_name().c_str());
      else strcpy(mf.back_2, "NONE");
      if (back[2] != NULL) strcpy(mf.back_3, back[2]->get_name().c_str());
      else strcpy(mf.back_3, "NONE");
      if (front[0] != NULL) strcpy(mf.front_1, front[0]->get_name().c_str());
      else strcpy(mf.front_1, "NONE");
      if (front[1] != NULL) strcpy(mf.front_2, front[1]->get_name().c_str());
      else strcpy(mf.front_2, "NONE");
      if (front[2] != NULL) strcpy(mf.front_3, front[2]->get_name().c_str());
      else strcpy(mf.front_3, "NONE");
      if (tileset != NULL) strcpy(mf.tileset, tileset->get_name().c_str());
      else strcpy(mf.tileset, "NONE");
    }

    void Load(std::string nm);
    void Save(std::string nm);

    void Start(int tw, int th, CacheBitmap *t);
    void SetTileset(CacheBitmap *t);
    void DrawLayer(int l);
    void DrawBack();
    void DrawFront();

    void SetBackground(int x, CacheBitmap *bit) {back[x]=bit;}
    void SetFront(int x, CacheBitmap *bit) {front[x]=bit;}

    void SetName(std::string nm) {name = nm;}
    std::string GetName() {return name;}

    void SetInternalName(std::string nm) {internal_name=nm;}
    std::string GetInternalName() {return internal_name;}

    CacheBitmap *GetTileset() {return tileset;}

    bool SetTile(int l, int x, int y, int v) {
      if (x < 0) return false;
      if (x >= w) return false;
      if (y < 0) return false;
      if (y >= h) return false;
      tiles[l][x][y] = v;
      return true;
    }
    int GetTile(int l, int x, int y) {
      if (x < 0) return -2;
      if (x >= w) return -2;
      if (y < 0) return -2;
      if (y >= h) return -2;
      return tiles[l][x][y];
    }

    void SetTileCollision(int t, int v) {
      collision_map[t] = v;
    }
    short int GetTileCollision(int t) {
      return collision_map[t];
    }

    bool IsFree(int x, int y);
    bool IsFreeAbove(int x, int y);

    int GetW() {return w;}
    int GetH() {return h;}
    void SetW(float v) {w=v;}
    void SetH(float v) {h=v;}

    void Resize(float tw, float th);

    ~Map();
};


std::string GetRealMapName(std::string filename);

void SpawnPeople();
void SpawnPerson(SpawnPoint *sp);

extern Map *actual_map;

#endif
