/* World.h
 *
 * Interface definition for the World class, which contains all of the in-game
 * objects of Triangle World and dispatches function calls to them.
 */

#ifndef WORLD_H_INCLUDED
#define WORLD_H_INCLUDED 1

#include <vector>
#include <fstream>
#include <string>
#include "Tuple.h"
#include "Ball.h"
#include "Obstruction.h"
#include "Vertex.h"
#include "Edge.h"
#include "Triangle.h"
#include "Club.h"
#include "Camera.h"
#include "Meter.h"

class World
{

/* The Parser works very closely with the World since
 * the parser must set up the world based on the input
 * file. Thus, we allow the parser to mess with World's
 * private stuff.
 */
friend class Parser;

private:
	// Constants
	static const double MAX_DT;
	static const double DEF_GRAVITY;
	static const double METER_INC;
	static const double METER_MAX;
	static const double METER_MULT;

	// Member Variables
	Tuple						gravity_;
	Ball						ball_;
	Club						club_;
	Meter						meter_;
	bool						meterActive_;
	bool						meterIncreasing_;
	bool						gameOver_;
	bool						light_;
	bool						ballDebug_;
	int							strokes_;
	std::vector<Obstruction*>	obstructions_;
		/* A note on the obstructions_ vector
		 *
		 * Everything in obstructions_ is heap allocated by World's
		 * "addTriangle", "addEdge", and "addVertex" functions. They will be
		 * deallocated by the clearObstructions() function which is called in
		 * the destructor.
		 */

	// Private Functions
	void destroyWorld();			// Removes destruction of world to another function.
	void setupLight();				// Call once to tell glut how to turn on the light.
									// Called in init().
	void clearObstructions();		// Safely clears obstruction vector

public:
	// Public camera so TriWorld can poke at it
	Camera camera;

	// Constructors/Destructor
	World(const Tuple& gravity = Tuple(0.0, DEF_GRAVITY, 0.0), bool light = true); // light on by default
	virtual ~World();

	// Member Functions
	void init();                    // Initialize World (call only ONCE!)
	void draw();					// Draw world and all its contents
	void timeStep(double dt);		// Move the ball and check for collisions
	void swing();					// Swing the golf club (if ball is ready)

	// Turn lights on/off in the world
	void lightOn();
	void lightOff();
	void lightToggle() {light_ ? lightOff() : lightOn();}

	// Object Adders
	Triangle* addTriangle(Vertex* v1, Vertex* v2, Vertex* v3);
	Edge* addEdge(Vertex* v1, Vertex* v2);
	Vertex* addVertex(Tuple v1, Tuple color);

	// Utility
	void setBottom(double newBottom) {ball_.setMinY(newBottom);} // sets bottom of world
	const Tuple* pBallPosition() const {return ball_.pPosition();}
	void ballDebugToggle();
	void rollDebugToggle();

	// Accessors
	const bool gameOver() const {return gameOver_;}
	const int strokes() const {return strokes_;}
};

#endif // WORLD_H_INCLUDED
