#ifndef _HPP_KUNGFLOW_STADIUM
#define _HPP_KUNGFLOW_STADIUM

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

class KungFlowGame;
class PlayState;
class Stage;
class PhysicsObject;
class Tile;
class Space;

//
// container of the 'physical' world (like an organisation of tiles, or maybe even an actual stadium
//

struct TriggerPosition {
  Vector2 position;
  bool triggered;
};

struct SpaceGenConfig {
  int minLength;
  int maxLength;
  int minWidth;
  int maxWidth;
  int widthVariation;
  int maxSeparatorLength;
  int minDescent;
  int maxDescent;
};

class Stadium {

  public:

    Stadium(const KungFlowGame *game, const PlayState *playState, Stage *stage);
    virtual ~Stadium();
    //std::vector<Object*> GetReplayObjects();

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

    void SetFlowTilesPerBeat(float tpb = 1.0f);
    //void RecalibrateFlow();

    //Vector2 GetPitchDimensions() const { return pitchDimensions; }
    //const int *GetDimensions() const { return dimensions; };
    const Vector2 GetGoodGuySpawnPoint(int id) const;// { return Vector2(GetDimensions()[0] * 0.5f, GetDimensions()[1] * 0.5f); }

    void GenerateTriggeredSpaces();
    const Space *GetClosestSpace(const Vector2 &position) const;

    //bool InRange(int x, int y) const;
    //bool InRange(const Vector2 &position) const;
    float GetBaseZPosition(const Vector2 &position) const;
    const Tile *GetTile(int x, int y) const;
    const Tile *GetTile(const Vector2 &position) const;
    const Tile *GetTile_NoRangeCheck(int x, int y) const;
    const Tile *GetTile_NoRangeCheck(const Vector2 &position) const;
    //bool IsTraversable(int x, int y) const;
    bool IsTraversable(int x, int y) const;
    bool IsTraversable(const Vector2 &position) const;

    //void GetAmbientColor(Uint8 colorRGB[]) { return float[3]{ 100, 100, 140 } }
    std::array<float, 3> GetAmbientColor() const { std::array<float, 3> color = {{ 0.1f, 0.2f, 1.0f }}; return color; }
    //std::array<float, 3> GetGradingColor() const { std::array<float, 3> color = {{ 1.0f, 0.7f, 0.3f }}; return color; }
    std::array<float, 3> GetGradingColor() const { std::array<float, 3> color = {{ 0.8f, 0.7f, 0.5f }}; return color; }

    // automatic (forced) movement
    int GetFlowAxis() const { return flowAxis; }
    Vector2 GetFlowDirection() const { return flowDirection; }
    float GetFlowVelocity() const { return flowVelocity; }
    Vector2 GetFlowMovement() const { return flowMovement; }
    Vector2 GetFlowPosition() const { return flowPosition; }

    const TriggerPosition GetTriggerPosition() const { return triggerPosition; }
    void UpdateTriggerPosition(const Vector2 &position, bool triggered) { triggerPosition.position = position; triggerPosition.triggered = triggered; }

  private:

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

//    float rndTmp[10000];
    //Vector2 pitchDimensions;

    Object *backgroundObject[2];
    Sprite *backgroundSprite[2];
    //SpatialNode *backgroundPositioner;

    //std::vector<Tile> tiles;
    //int dimensions[2];
    //std::vector<Tile*> tiles;
/*
    Sprite *isoTileSprite1;
    Sprite *isoTileSprite2;
    Sprite *isoTileSprite3;
    //Sprite *isoTreeSprite;
    //Object *testTreeObject1;
    //Object *testTreeObject2;
    //Object *testTreeObject3;
*/
    float flowTilesPerBeat;
    int flowAxis;
    Vector2 flowDirection;
    float flowVelocity;
    Vector2 flowMovement;
    Vector2 flowPosition; // how far are we?

    TriggerPosition triggerPosition;

    SpaceGenConfig spaceGenConfig;
    unsigned int numSpaces;
    unsigned int spacesLoaded;
    unsigned int lastSpaceZ;
    std::vector<Space*> spaces;

};

#endif
