#ifndef SDPSL_H
#define SDPSL_H

// SDPSL
// Copyright (c) 1995-2004, Timothy M. Shead
//
// Contact: tshead@k-3d.com
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/** \file
		\brief Declares the SDPSL library interface, which returns information (including parsed and cached metadata) about a RenderMan Shading Language shader
		\author Tim Shead (tshead@k-3d.com)
*/

#include <iosfwd>
#include <list>
#include <string>

namespace sdpsl
{

/// Encapsulates an argument to a Pixar RenderMan Shading Language shader
class argument
{
public:
	/// Enumerates Shading Language storage classes
	typedef enum
	{
		UNIFORM,
		VARYING,
	} storage_class_t;

	/// Enumerates Shading Language data types
	typedef enum
	{
		FLOAT,
		POINT,
		VECTOR,
		NORMAL,
		COLOR,
		MATRIX,
		STRING,
	} type_t;

	/// Enumerates "extended" data types
	typedef enum
	{
		EX_FLOAT,
			EX_TIME,
			EX_ANGLE,
			EX_DISTANCE,
			EX_AREA,
			EX_VOLUME,
			EX_MASS,
			EX_FORCE,
			EX_PRESSURE,
		EX_POINT,
		EX_VECTOR,
		EX_NORMAL,
		EX_COLOR,
		EX_MATRIX,
		EX_STRING,
			EX_TEXTURE,
			EX_SPACE,
	} extended_type_t;

	/// Stores the argument name
	const  std::string name;
	/// Stores the Shading Language storage class
	const storage_class_t storage_class;
	/// Stores the Shading Language data type
	const type_t type;
	/// Stores the extended data type
	const extended_type_t extended_type;
	/// Stores the number of array elements for this argument
	const unsigned long array_count;
	/// Stores the coordinate system that this argument is declared within
	const std::string space;
	/// Stores true iff this argument is an output (message passing) argument
	const bool output;
	/// Stores the argument's default value as a string
	const std::string default_value;

	// Enforce strict initialization
	explicit argument(const std::string Name, const storage_class_t StorageClass, const type_t Type, const extended_type_t ExtendedType, const unsigned long ArrayCount, const std::string Space, const bool Output, const std::string DefaultValue);
};

/// Encapsulates a Pixar RenderMan Shading Language shader
class shader
{
public:
	/// Enumerates shader types
	typedef enum
	{
		SURFACE,
		LIGHT,
		VOLUME,
		DISPLACEMENT,
		TRANSFORMATION,
		IMAGER,
	} type_t;

	/// Stores the shader file
	const std::string file_path;
	/// Stores the shader name
	const std::string name;
	/// Stores the shader author(s)
	const std::string authors;
	/// Stores the shader copyright
	const std::string copyright;
	/// Stores a brief description of the shader
	const std::string brief_description;
	/// Stores the shader type
	type_t type;
	/// Stores the shader arguments
	typedef std::list<argument> arguments_t;
	const arguments_t arguments;
	
	// Enforce strict initialization
	explicit shader(const std::string FilePath, const std::string Name, const std::string Authors, const std::string Copyright, const std::string BriefDescription, const type_t Type, const arguments_t Arguments);
	
	/// Establish equivalency based on name-only
	friend bool operator==(const shader& LHS, const shader& RHS)
	{
		return LHS.name == RHS.name;
	}
	
	/// Establish order based on name-only
	friend bool operator<(const shader& LHS, const shader& RHS)
	{
		return LHS.name < RHS.name;
	}
};

/// A collection of shaders
typedef std::list<shader> shaders_t;

// Serialization
std::ostream& operator<<(std::ostream& Stream, const argument::storage_class_t&);
std::istream& operator>>(std::istream& Stream, argument::storage_class_t&);
std::ostream& operator<<(std::ostream& Stream, const argument::type_t&);
std::istream& operator>>(std::istream& Stream, argument::type_t&);
std::ostream& operator<<(std::ostream& Stream, const argument::extended_type_t&);
std::istream& operator>>(std::istream& Stream, argument::extended_type_t&);
std::ostream& operator<<(std::ostream& Stream, const shader::type_t& Value);
std::istream& operator>>(std::istream& Stream, shader::type_t& Value);

/// Parses preprocessed RenderMan shading language source-code, returning shader data (note: could return an empty collection, SourcePath is for informational messages only)
shaders_t parse_source(std::istream& Stream, const std::string SourcePath);
/// Parses a shader metafile, returning shader data (note: could return an empty collection, SourcePath and MetafilePath are for informational messages only)
shaders_t parse_metafile(std::istream& Stream, const std::string SourcePath, const std::string MetafilePath);
/// Generates a shader metafile from a collection of shaders
void generate_metafile(std::ostream& Stream, const shaders_t Shaders);

} // namespace sdpsl

#endif // SDPSL_H
