#pragma once
#include "utilities.hh"


/*= INPUT FILES ==============================================================*/

// Type of input chunk
enum class E_ShaderInputChunk {
	CODE ,
	INCLUDE
};

// Input chunk data
struct T_ShaderInputChunk
{
	E_ShaderInputChunk type;
	std::string text;
	uint32_t lines;

	T_ShaderInputChunk( ) = default;
	T_ShaderInputChunk(
			__rd__ const E_ShaderInputChunk type ,
			__rd__ std::string text ,
			__rd__ const uint32_t lines )
		: type( type ) , text( std::move( text ) ) , lines( lines )
	{ }
};

// Input file type
enum class E_ShaderInput {
	CHUNK ,			// Chunk that may be repeated
	LIBRARY ,		// Library (will only be loaded once)

	// "Main" shader source files
	VERTEX , FRAGMENT ,
};

// Preprocessing errors
struct T_ShaderInputError
{
	uint32_t line;
	std::string error;
};

// Source file
struct T_ShaderInput
{
	E_ShaderInput type = E_ShaderInput::CHUNK;
	std::vector< T_ShaderInputChunk > chunks;
	std::vector< T_ShaderInputError > errors;

	bool load( __rd__ std::string const& path );
};
using P_ShaderInput = std::unique_ptr< T_ShaderInput >;


// Type of shader
enum class E_ShaderType {
	VERTEX , FRAGMENT ,
};


// Errors in shader code - the errors it represents may come from either
// the input loader, the shader loader or the driver.
struct T_ShaderError
{
	std::string source;
	uint32_t line;
	std::string error;
};

// Shader code after reconstitution
// XXX rename this
struct T_Frankenshader
{
	E_ShaderType type;
	std::vector< uint32_t > starts;		// Position of chunk in source file
	std::vector< uint32_t > counts;		// Chunk lengths
	std::vector< std::string > sources;	// Chunk source files
	std::string code;
	std::vector< T_ShaderError > errors;
};
using P_Frankenshader = std::unique_ptr< T_Frankenshader >;

// XXX test for the loader
struct T_ShaderCodeLoader
{
	bool load( __rd__ std::string const& name ,
			__wr__ T_Frankenshader& code );

	T_ShaderInput const* getInput( __rd__ std::string const& name );
	void removeInput( __rd__ std::string const& name );

    private:
	std::map< std::string , P_ShaderInput > files;
};


void testLoadShaderFile( );