/*****************************************************************************
 * $Id: eng_import.hh,v 1.17 2006/08/20 16:34:17 devel Exp $
 * @file
 * @author	Jim E. Brooks  http://www.jimbrooks.org
 * @brief	Imports 3D models (from Blender) as Palomino Objects.
 * @remarks	See implementation.html for the data format that is imported etc.
 *//*
 * LEGAL:	COPYRIGHT (C) JIM E. BROOKS 2005
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE (GPL).
 *****************************************************************************/

#ifndef ENG_IMPORT_HH
#define ENG_IMPORT_HH 1

////////////////////////////////////////////////////////////////////////////////
/// @brief Holds results of importing one 3D model.
/// @remarks A map of these is used to let Objects share a 3D model (save memory).
class Importation
{
COPYABLE_DEFAULT(Importation)  // compiler-generated copying methods suffice
public:
        Importation( void )
        :   mVertexCnt(0),
            mNormalCnt(0),
            mLocalVertexs(NULL),            // to be parsed
            mLocalNormals(NULL),            // to be parsed
            mPolygonList(new PolygonList)   // start with empty PolygonList
        {
            // nothing
        }
		~Importation()
		{
            // nothing
		}

        uint                            GetVertexCnt( void )    { return mVertexCnt; }
        uint                            GetNormalCnt( void )    { return mNormalCnt; }
        SharedPtrArr<const LocalVertex> GetLocalVertexs( void ) { return mLocalVertexs; }
        SharedPtrArr<const Normal>      GetLocalNormals( void ) { return mLocalNormals; }
        SharedPtr<PolygonList>          GetPolygonList( void )  { return mPolygonList; }

        void    SetVertexCnt( uint vertexCnt )                     { mVertexCnt = vertexCnt; }
        void    SetNormalCnt( uint normalCnt )                     { mNormalCnt = normalCnt; }
        void    SetLocalVertexs( const LocalVertex* localVertexs ) { mLocalVertexs = localVertexs; }
        void    SetLocalNormals( const Normal* localNormals )      { mLocalNormals = localNormals; }
        void    SetPolygonList( PolygonList* polygonList )         { mPolygonList = polygonList; }

        // A "vertex group" is a set of vixs associated with a name.
        // Corresponds to a Blender Vertex Group which are given names.
        vector<Vix>& NewVertexGroup( const string& name, const uint vixCnt )
        {
            // Tricky: a copy of an empty STL vector is inserted into the STL map,
            // and the mapped vector is returned by reference.
            ASSERT( mVertexGroupMap.find( name ) == mVertexGroupMap.end() );
            mVertexGroupMap[name] = vector<Vix>();       // insert empty vector
            vector<Vix>& vec = mVertexGroupMap[name];    // reference to vector
            vec.resize( vixCnt );                        // resize the vector (the one in the map)
            return vec;                                  // return reference to vector (the one in the map)
        }

        // @return Pointer to vix container of existing Vertex Group.  If error, returns an empty vector.
        const vector<Vix>& GetVertexGroupVixs( const string& name )
        {
            if ( mVertexGroupMap.find( name ) != mVertexGroupMap.end() )
            {
                return mVertexGroupMap[name];  // it exists
            }
            else
            {
                ASSERT(0);  // oops, no Vertex Group has that name
                static vector<Vix> empty;
                return empty;
            }
        }        

private:
	// These members (and thus the class) are all copyable.
	uint                        	mVertexCnt;
	uint                    		mNormalCnt;
	SharedPtrArr<const LocalVertex>	mLocalVertexs;          ///< correlates to Blender "verts" list
	SharedPtrArr<const Normal>		mLocalNormals;          ///< correlates to Blender normals
	SharedPtr<PolygonList>      	mPolygonList;			///< correlates to Blender "faces" list
	typedef map< string, vector<Vix> > VertexGroupMap;
	VertexGroupMap                  mVertexGroupMap;		///< correlates to Blender's named "vertex groups"
};

////////////////////////////////////////////////////////////////////////////////
/// @brief Factory that produces Importation objects from importing models from Blender.
class ImportFactory
{
PREVENT_COPYING(ImportFactory)
public:
					ImportFactory( void );
					~ImportFactory();
	bool			Import( Importation& importation /*OUT*/, const string& fnameModel );
	const string&	GetErrorText( void ) { return mErrorText; } // set if Import() failed

private:
	void			Clear( void );
	void			ClearPolygon( void );
	bool			ToNextLine( void );
	bool			ImportVertexs( void );
	bool			ImportNormals( void );
	bool			ImportPolygonBegin( void );
	bool			ImportPolygonEnd( void );
	bool			ImportPolygonRgba( void );
	bool			ImportPolygonVixArray( void );
	bool			ImportVertexGroup( void );

private:
	// mImportation is a pointer: the easy way to clear it for
	// the next importing is to just construct a new one.
	Importation*                mImportation;			///< new one made for every import
	map<string,Importation>     mImportationSaved;		///< saved import keyed by model filename
	ifstream					mIstrm;					///< input stream from model filename
	string						mErrorText;
	typedef map<string,Importation>::iterator ItrImportation;

	// Temporaries for a polygon:
	PolygonAttribs*				mPolygonAttribs;
	RGBA						mPolygonRgba;
	Texture*					mPolygonTexture;
	uint						mPolygonTexCoordCnt;
	uint						mPolygonVixCnt;
};

extern ImportFactory gImportFactory;

#endif // ENG_IMPORT_HH
