#pragma once
#include "../includes.h"
#include "../config.h"
#include "regex.h"

class SCENE_TOKEN_TYPE {
	private:
		int _a,_b,_c,_d;
	public:
		SCENE_TOKEN_TYPE(int a, int b, int c, int d);
		
		SCENE_TOKEN_TYPE operator|(const SCENE_TOKEN_TYPE& o) const;
		bool operator&(const SCENE_TOKEN_TYPE& o) const;
		bool operator==(const SCENE_TOKEN_TYPE& o) const;
		bool operator<(const SCENE_TOKEN_TYPE& o) const;
		
		void increment(void);
		void print(void);
		string get_as_string(void);
};

#define                STT_BLOCK_START SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00000001)
#define                  STT_BLOCK_END SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00000002)

#define                 STT_WHITESPACE SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00000004)
#define                    STT_NEWLINE SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00000008)
#define                        STT_EOF SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00000010)

#define                STT_INHERITANCE SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00000020)

#define                    STT_INTEGER SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00000040)
#define                    STT_DECIMAL SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00000080)

#define                     STT_STRING SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00000100)

#define               STT_COMMENT_LINE SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00000200)
#define        STT_COMMENT_BLOCK_START SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00000400)
#define          STT_COMMENT_BLOCK_END SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00000800)

#define             STT_CONTEXT_CAMERA SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00001000)
#define              STT_CONTEXT_IMAGE SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00002000)
#define              STT_CONTEXT_LIGHT SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00004000)
#define           STT_CONTEXT_MATERIAL SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00008000)
#define             STT_CONTEXT_OBJECT SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00010000)
#define              STT_CONTEXT_SCENE SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00020000)

#define         STT_ATTRIB_IMAGE_WIDTH SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00040000)
#define        STT_ATTRIB_IMAGE_HEIGHT SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00080000)
#define       STT_ATTRIB_IMAGE_SAMPLES SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00100000)

#define     STT_ATTRIB_CAMERA_POSITION SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00200000)
#define       STT_ATTRIB_CAMERA_CENTER SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00400000)
#define           STT_ATTRIB_CAMERA_UP SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x00800000)

#define     STT_ATTRIB_CAMERA_APERTURE SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x01000000)
#define  STT_ATTRIB_CAMERA_IMAGE_PLANE SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x02000000)
#define STT_ATTRIB_CAMERA_FOCAL_LENGTH SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x04000000)

#define               STT_ATTRIB_COLOR SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x08000000)

#define                   STT_CONTEXTS SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x0003F000) //UPDATE ME!!!
#define                        STT_ALL SCENE_TOKEN_TYPE(0x00000000,0x00000000,0x00000000,0x0FFFFFFF) //UPDATE ME!!!

typedef map<SCENE_TOKEN_TYPE,Regex*> type_token_regexes;
typedef map<SCENE_TOKEN_TYPE,string*> type_token_names;
class Token {
	friend class SCENE_TOKEN_TYPE;
	public:
		string* content;
		SCENE_TOKEN_TYPE* type;
		//UPDATE COPY CONSTRUCTOR!!!

		static type_token_regexes* regexes;
		#ifdef DEBUG_TOKENS
		static type_token_names* names;
		#endif

	public:
		static void init(void);
		static void deinit(void);

		inline bool is(SCENE_TOKEN_TYPE t) {
			return *type&t;
		}

		Token(string new_content, SCENE_TOKEN_TYPE new_type);
		Token(Token& t);
		~Token();

		string get_content_printable(void);

	private:
		static const char* get_name(SCENE_TOKEN_TYPE* t);
};