#ifndef SCOP_H
# define SCOP_H

# include <stdio.h>
# include <string.h>
# include <unistd.h>
# include <fcntl.h>
# include <stdlib.h>
# include <assert.h>
# include <math.h>
# include <float.h>
# include <stdbool.h>
# include <GL/glew.h>
# include <GLFW/glfw3.h>

# include "vec3.h"

# define SUCCESS 0
# define FAILURE -1
# define BREAK 1
# define TRUE 1
# define FALSE 0

# define BUFFER_SIZE 4096

# define EPSILON 0.000001

typedef enum e_gl_buf_type t_gl_buf_type;

enum e_gl_buf_type {
	VERTEX,
	UV,
	NORMAL,
	INDEX,
	OTHER
};

typedef struct s_cam t_cam;
typedef struct s_window t_window;
typedef struct s_buf_d t_buf_d;
typedef struct s_buf_ui t_buf_ui;
typedef struct s_buf_s t_buf_s;
typedef struct s_obj t_obj;
typedef struct s_env t_env;

struct s_cam {
	double fov;
	double aspect;
	double near;
	double far;
};

struct s_window {
	int width;
	int height;
};

struct s_buf_d {
	double *data;
	size_t ptr;
	size_t len;
};

struct s_buf_ui {
	unsigned int *data;
	size_t ptr;
	size_t len;
};

struct s_obj {
	t_buf_d vertices;
	t_buf_d uvs;
	t_buf_d normals;
	t_buf_ui vertices_indices;
	t_buf_ui uvs_indices;
	t_buf_ui normals_indices;
};

struct s_env {
	char *file_name;
	t_cam camera;
	t_window window;
	t_obj object;
	float *vbo_data;
	GLuint shader_program;
	GLuint vertex_shader;
	GLuint fragment_shader;
	t_vec3 translate;
	t_vec3 rotate;
	t_vec3 scale;
	bool rotating;
	bool texture;
	bool lighting;
	float texture_level;
};

int parse(t_env *e, int argc, char **argv);
void set_params(t_env *e, int argc, char **argv);
int parse_file(t_env *e);

int parse_line(t_env *e, char *line);
t_gl_buf_type parse_gl_buf_type(char *token);
void parse_triangulate(t_buf_ui *indices, int token_count);
void parse_append_data_tmp(t_buf_ui *indices, int vertex_count, unsigned int *data_tmp);

int parse_token(t_env *e, char *token, t_gl_buf_type gl_buf_type);
int parse_append_data_d(t_buf_d *buffer, char *token);
int parse_append_data_ui(t_buf_ui *buffer, char *token);

void center_vertices(t_buf_d *vertices);

void free_env(t_env *e);
void init_window(t_env *e);
void init_camera(t_env *e);
void init_object(t_env *e);
void init_env(t_env *e);

int run(t_env *e);

#endif

