#ifndef _HPP_KUNGFLOW_SPACE
#define _HPP_KUNGFLOW_SPACE

#include "gaia/gaia.hpp"
using namespace gaia;

#include "physicsobject.hpp"

class KungFlowGame;
class PlayState;
class Stage;
class Stadium;
class Tile;
class Decoration;

//
// a space is a sort of 'room' within the stadium. this is nice for both culling and convenience purposes.
//

class Space {

  public:

    Space(const KungFlowGame *game, const PlayState *playState, const Stage *stage, const Stadium *stadium, int x, int y, int w, int h);
    virtual ~Space();

    virtual void OnStepPhysicsTime() {};
    //virtual void PostStepPhysicsTime() {};
    virtual void GetPhysicsObjects(std::vector<PhysicsObject*> &targetContainer) const {};
    virtual void Draw(const Viewport &viewport, const Camera &camera) const {};
    virtual void DrawBackLayer(const Viewport &viewport, const Camera &camera) const {};
    virtual void DrawFrontLayer(const Viewport &viewport, const Camera &camera) const {};
    virtual void DrawLights() const {};

    bool Contains(int xpos, int ypos) const {
      if (xpos >= x && xpos < x + w && ypos >= y && ypos < y + h) return true; else return false;
    }
    bool Contains(const Vector2 &pos) const {
      //if ((int)pos.coords[0] >= x && pos.coords[0] < x + w && pos.coords[1] > y && pos.coords[1] < y + w) return true; else return false;
      return Contains(int(round(pos.coords[0])), int(round(pos.coords[1])));
    }

    Vector2 GetCenterPosition() const { return Vector2(x + (w - 1) / 2.0f, y + (h - 1) / 2.0f); }

    const Tile *GetTile(int xpos, int ypos) const;
    const Tile *GetTile(const Vector2 &position) const;
    const Tile *GetTile_NoRangeCheck(int xpos, int ypos) const { return tiles.at((xpos - x) * h + (ypos - y)); }
    const Tile *GetTile_NoRangeCheck(const Vector2 &position) const { return GetTile_NoRangeCheck(int(round(position.coords[0])), int(round(position.coords[1]))); }
    //bool IsTraversable(int x, int y) const;
    bool IsTraversable(int xpos, int ypos) const;
    bool IsTraversable(const Vector2 &position) const;

    virtual std::vector<Vector2> GetSpawnPositions() const { return std::vector<Vector2>(); }

    const int x, y, w, h; // yes, public variables. f&ck the police!

  protected:

    const KungFlowGame *game;
    const PlayState *playState;
    const Stage *stage;
    const Stadium *stadium;

    std::vector<Tile*> tiles;
    std::vector<Decoration*> decorationsBack;
    std::vector<Decoration*> decorationsFront;

};

class RooftopSpace : public Space {

  public:

    RooftopSpace(const KungFlowGame *game, const PlayState *playState, const Stage *stage, const Stadium *stadium, int x, int y, int w, int h, int z);
    virtual ~RooftopSpace();

    virtual void OnStepPhysicsTime() override;
    //virtual void PostStepPhysicsTime() override;
    virtual void GetPhysicsObjects(std::vector<PhysicsObject*> &targetContainer) const override;
    void Draw(const Viewport &viewport, const Camera &camera) const override;
    virtual void DrawBackLayer(const Viewport &viewport, const Camera &camera) const override;
    virtual void DrawFrontLayer(const Viewport &viewport, const Camera &camera) const override;
    virtual void DrawLights() const override;

    virtual std::vector<Vector2> GetSpawnPositions() const override;

  private:

    float baseZPosition;

};

#endif
