// Scene.h: interface for the Scene class.
//
//////////////////////////////////////////////////////////////////////

#include <math.h>
#include "Vector3.h"

#include "GeomObj.h"
#include "Shape.h"

#if !defined(AFX_SCENE_H__7B1F2882_5D01_4D9B_B462_D6B214D67BD6__INCLUDED_)
#define AFX_SCENE_H__7B1F2882_5D01_4D9B_B462_D6B214D67BD6__INCLUDED_

#include <assert.h>
#ifdef MACOSX
#include <glut.h>
#else
#include <GL/glut.h>
#endif
#include <time.h>

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <iostream>
#include <fstream>
#include <strstream>
#ifdef WIN_32
using namespace std;
#include <windows.h>
#endif

#include <string>
using namespace std;

static bool doEdges2 = false;

//@@@@@@@@@@@@@@@@@@@@ light class @@@@@@@@@@@@@@@@@@@
class Light{ // for a linked list of light sources’ color and position
public:
	float radius;
	Point3 pos;
	Color3 color;
	Light* next;
	void setPosition(Point3 p);
	void setColor(Color3 c);
	Light();
	Point3 getPos(float f, float numFeelers);
};


// @@@@@@@@@@@@@@@@@@@@@ Affine4 class @@@@@@@@@@@@@@@@
class Affine4 {// manages homogeneous affine transformations
// including inverse transformations
// and a stack to put them on
// used by Scene class to read SDL files
public:
	float m[16]; // hold a 4 by 4 matrix
	Affine4();
	void setIdentityMatrix();
	void set(Affine4 a);
	void preMult(Affine4 n);
	void postMult(Affine4 n);
}; // end of Affine4 class

//@@@@@@@@@@ AffineNode class @@@@@@@@@@@
class AffineNode{
// used by Scene class to read SDL files
public:
	Affine4 * affn;
	Affine4 * invAffn;
	AffineNode * next;
	AffineNode()
	{
		next = NULL;
		affn = new Affine4; // new affine with identity in it
		invAffn = new Affine4; // and for the inverse
	}
	~AffineNode() //destructor
	{
		delete affn;
		delete invAffn;
	}
};
//@@@@@@@@@@@@@@@@ AffineStack class @@@@@@@@@@@@
class AffineStack{
// used by Scene class to read SDL files
public:
	AffineNode * tos;
	AffineStack()//default constructor;puts identity on top
	{
		tos = new AffineNode; // node with identity in it
		tos->next = NULL;
	}
	void dup();
	void setIdentity();// make top item the identity matrix
	void popAndDrop();
	void releaseAffines(); // pop and drop all remaining items
	void rotate(float angle, Vector3 u);
	void scale(float sx, float sy, float sz);
	void translate(Vector3 d);
}; // end of AffineStack class

//@@@@@@@@@@@@@@@@@ DefUnit & DefUnitStack classes @@@@@@@@@@@@@@
//used in Scene to read SDL files
class DefUnit {
	// developed by Steve Morin
public:
	DefUnit(string n, string s);
	string name;
	string stuff;
};

class DefUnitStack {
public:
	DefUnitStack() {stack = NULL;}
	void push(string n, string s);
	void print();
	int search(string s);
	string contents(string s);
	void release();
private:
	struct D4S {
		DefUnit *current;
		struct D4S *next;
	} d4s;
	D4S *stack;
}; // end of DefUnitStack class

//+++++++++++++ TokenType +++++++++++++
		enum mTokenType {IDENT, LIGHT, ROTATE, TRANSLATE,
		SCALE, PUSH, POP, IDENTITYAFFINE, FOG, SHADOWQUALITY,
		GLOBALAMBIENT, BACKGROUND, PIXELSIZE, MINREFLECTIVITY,
		MINTRANSPARENCY, MAXRECURSIONDEPTH, CUBE, SPHERE, TORUS,
		PLANE, SQUARE, CYLINDER, CONE, TAPEREDCYLINDER,TETRAHEDRON,
		OCTAHEDRON, DODECAHEDRON, ICOSAHEDRON,BUCKYBALL, TEAPOT,
		DIAMOND,UNION,INTERSECTION, DIFFERENCEa, MAKEPIXMAP,
		MESH, DEFAULTMATERIALS, AMBIENT, DIFFUSE,SPECULAR,
		SPECULARFRACTION, SURFACEROUGHNESS,EMISSIVE, SPECULAREXPONENT,
		SPEEDOFLIGHT, ENVLIGHTSPEED, TRANSPARENCY,REFLECTIVITY, PARAMETERS, TEXTURE,
		LFTCURLY, RGHTCURLY, DEF, USE, T_NULL, F_EOF, UNKNOWN };



//@@@@@@@@@@@@@@@@@@@ Boolean @@@@@@@@@@@@@@@@@@
class Boolean: public GeomObj{
public:
	GeomObj *left, *right;
	Boolean():left(NULL),right(NULL){}
	virtual void drawOpenGL()
	{ // just draw its children
		if(left)left->drawOpenGL();
		if(right)right->drawOpenGL();
	}
};
//@@@@@@@@@@@@@@@@@@@@ UnionBool @@@@@@@@@@@@@@@@
class UnionBool : public Boolean{
public:
	UnionBool(){Boolean();} //constructor
};
//@@@@@@@@@@@@@@@@@@@@ IntersectionBool @@@@@@@@@@@@@@@@
class IntersectionBool : public Boolean{
public:
	IntersectionBool(){Boolean();}
};
//@@@@@@@@@@@@@@@@@@@@ DifferenceBool @@@@@@@@@@@@@@@@
class DifferenceBool : public Boolean{
public:
	DifferenceBool(){Boolean();}
};




//@@@@@@@@@@@@@@@@@@@@ scene class @@@@@@@@@@@@@@@@@@@
class Scene{
public:
	Scene(); //default constructor
	Scene(string fname);
	virtual ~Scene();
	Light *light;  // attach linked list of lights here
	GeomObj * obj;  // attach the object list here
	Color3 background, ambient;
	float envLightSpeed;
	int maxRecursionDepth;
	int pixelSize;
	//must #include RGBpixmap.h to have following texture fields
	//RGBpixmap pixmap[8]; //list of attached pixmaps
	float minReflectivity, minTransparency;

	void freeScene();
	void makeLightsOpenGL();
	void drawSceneOpenGL();
	void toggleEdges();
	bool read(string fname);
	GeomObj* getObject();
	bool isInShadow(Ray& f);
	Vector3 xfrmNormal(float* m, Vector3 INnormal);
	Color3 shade(Ray& ray);
	void getFirstHit(Ray& ray, Intersection& best);

private:
	// private stuff used only for reading a scene
	int line;
	int nextline;
	ifstream  *file_in;
	strstream *f_in;
	strstream temp_fin;
	DefUnitStack *def_stack;
	GeomObj * tail; // tail of object list
	AffineStack affStk; // affine stack
	Material currMtrl;
	float fogDensity;
	int shadowQuality;
	string nexttoken(void);
	float getFloat();
	bool isidentifier(string keyword);
	void cleanUp();
	mTokenType whichtoken(string keyword);

};

#endif // !defined(AFX_SCENE_H__7B1F2882_5D01_4D9B_B462_D6B214D67BD6__INCLUDED_)
