#ifndef _PIUMA_WAVEFRONT_H_
#define _PIUMA_WAVEFRONT_H_

#include "../lib/types.h"
#include "../lib/math.h"

typedef void *(*wf_alloc_t)(u64 size);
typedef void *(*wf_realloc_t)(void *ptr, u64 size);
typedef void  (*wf_free_t)(void *ptr);

/* Reassing wf_alloc and wf_free with your own alloc/free functions if you don't
 * want to use malloc and free.
 */
extern wf_alloc_t   wf_alloc;
extern wf_realloc_t wf_realloc;
extern wf_free_t    wf_free;

typedef u32 wf_index;
typedef u32 wf_size;


// Indices are 1-based in Wavefront. 0 is used to signal the index was omitted.
struct wf_face_index
{
	wf_index vertex;
	wf_index texture;
	wf_index normal;
};

struct wf_face
{
	wf_face_index indices[3];
};

struct wf_object
{
	char *name;
	// @Feature: groups are not supported yet
	char *material_name;

	// Vertices
	v4 *vertices;
	wf_size vertices_count;
	// Texture coordinates
	v3 *texture_coords;
	wf_size texture_coords_count;
	// Vertex normals
	v3 *normals;
	wf_size normals_count;
	// Faces
	wf_face *faces;
	wf_size faces_count;
};

struct wf_obj_file
{
	char *name;

	char **mtllib_names;
	wf_size mtllib_names_count;

	wf_object *objects;
	wf_size objects_count;
};




struct wf_material
{
	char *name;
	v3 Ka;  // ambient color
	v3 Kd;  // diffuse color
	v3 Ke;  // emissive color
	v3 Ks;  // specular color
	f32 Ns; // specular exposure
	f32 d;  // dissolved - transparency where 0.0 is fully transparent and 1.0 is opaque
	f32 Ni; // optical density - refractive index
	int illum; // illumination model
	/* illum is described at https://en.wikipedia.org/wiki/Wavefront_.obj_file#Basic_materials as follows:
	 * 0. Color on and Ambient off
	 * 1. Color on and Ambient on
	 * 2. Highlight on
	 * 3. Reflection on and Ray trace on
	 * 4. Transparency: Glass on, Reflection: Ray trace on
	 * 5. Reflection: Fresnel on and Ray trace on
	 * 6. Transparency: Refraction on, Reflection: Fresnel off and Ray trace on
	 * 7. Transparency: Refraction on, Reflection: Fresnel on and Ray trace on
	 * 8. Reflection on and Ray trace off
	 * 9. Transparency: Glass on, Reflection: Ray trace off
	 * 10. Casts shadows onto invisible surfaces
	 */

	char *map_Ka; // ambient texture map name
	char *map_Kd; // diffuse texture map name
	char *map_Ke; // emissive texture map name
	char *map_Ks; // specular color texture map name
	char *map_Ns; // specular highlight texture map name
	char *map_d;  // alpha texture map name
	char *bump;   // bump map name
	char *disp;   // displacement map name
	char *decal;  // stencil decal texture map name

	// @Feature: Texture options are not supported yet
};

struct wf_mtl_file
{
	char *name;

	wf_material *materials;
	wf_size materials_count;
};


bool wf_parse_obj(char *data, u64 size, const char *name, wf_obj_file *return_obj);
bool wf_parse_mtl(char *data, u64 size, const char *name, wf_mtl_file *return_mtl);
void wf_cleanup_obj(wf_obj_file *obj_file);
void wf_cleanup_mtl(wf_mtl_file *mtl_file);

#endif
