#pragma once
#include "../includes.h"
#include "../scene/bvh.h"
#include "../file_helpers.h"
#include "../points.h"
#include "../config.h"
#include "../texture.h"
#include "../render/trace.h"

struct Tile {
	int x,y,w,h;
};

class Renderer;

class TileRenderer;

inline int wrapper__render_tile(void*);
class TileRenderer {
	friend int wrapper__render_tile(void* arg);
	friend class Renderer;
	private:
		//Must have a separate matrix for each thread, and must have a separate reflection rotation matrix for each recursion level
		glLib::Math::Matrix::matrix<DT_FP,char>* _matrices_rotation[MAX_DEPTH];
		glLib::Math::Matrix::matrix<DT_FP,char>* _matrix_result;
		glLib::Math::Matrix::matrix<DT_FP,char>* _matrix_point;

		int _thread_id;
		SDL_Thread* _thread;

		Renderer* _renderer;

		Material* material_air;

	private:
		void init_matrices(void) {
			for (unsigned long i=0;i<MAX_DEPTH;++i) {
				_matrices_rotation[i] = new glLib::Math::Matrix::matrix<DT_FP,char>(3,3,GLLIB_MATRIX_EMPTY);
			}
			_matrix_result = new glLib::Math::Matrix::matrix<DT_FP,char>(3,1,GLLIB_MATRIX_EMPTY);
			_matrix_point = new glLib::Math::Matrix::matrix<DT_FP,char>(3,1,GLLIB_MATRIX_EMPTY);
		}
		void deinit_matrices(void) {
			for (int i=0;i<MAX_DEPTH;++i) {
				delete _matrices_rotation[i];
			}
			delete _matrix_result;
			delete _matrix_point;
		}

	public:
		TileRenderer(Renderer* renderer, int id);
		~TileRenderer();

		void thread_start(void);
		void thread_wait(void);

	private:
		unsigned int trace_get_intersect(Ray ray, RayInfo* info);
		inline RayInfo trace_shadow_ray(Ray ray);
		RayInfo trace_ray(Ray ray, DT_COL color[3], int depth, deque<Material*>* material_stack);

		Uint32 generate_trace_rays(int pix_x, int pix_y, DT_COL color[3], deque<Material*>* material_stack);
		int render_tile(void* data);
};