#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <map>


namespace lib_geo
{


class ObjMesh;


class ObjReaderCache
{
public:
	void SwapToMesh(ObjMesh& mesh);

public:
	std::vector<lm::vec3f>   verts;
	std::vector<lm::vec3f>   normals;
	std::vector<lm::vec2f>   uvs;
	std::vector<ObjFace>     faces;
	std::vector<ObjPolyline> lines;
};


class ObjMeshReader
{
public:
	bool Load( ObjMesh& mesh , const std::string& i_Filename );
	bool LoadStream( ObjMesh& mesh , std::istream& ist );

protected:
	bool LoadObjMain( ObjMesh& mesh , std::istream& ist , bool LoadMaterialFile );

	void InitializeWorkBuffer(void);

	void ReadVertLine           ( std::istream& ist , std::vector<lm::vec3f>& verts );
	void ReadNormLine           ( std::istream& ist , std::vector<lm::vec3f>& normals );
	void ReadUVLine             ( std::istream& ist , std::vector<lm::vec2f>& uvs );
	void ReadFaceLine           ( std::istream& ist , ObjReaderCache& cache );
	void ReadPolylineLine       ( std::istream& ist , std::vector<ObjPolyline>& lines );
	void ReadObjectSplitLine    ( std::istream& ist , ObjMesh& mesh , const ObjReaderCache& cache );
	void ReadGroupSplitLine     ( std::istream& ist , ObjMesh& mesh );
	void ReadMaterialSelectLine ( std::istream& ist , ObjMesh& mesh );
	void ReadMaterialGroup      ( std::istream& ist , ObjMesh& mesh );

	void SetLastObjectVertNum(ObjMesh& mesh, const ObjReaderCache& cache);

	bool CheckAndModifyContinueToNextLine(std::string& s) const;


private:
	std::map<std::string, int>  m_MatIdxMap;
	int                         m_PrimaryMatIdx;

	std::map<std::string, int>  m_GroupIdxMap;
	int                         m_PrimaryGroupIdx;

	std::string                 m_LoadWorkDirPath;
};


class ObjMeshWriter
{
public:
	bool Save( const ObjMesh& mesh , const std::string& i_Filename ) const;
	bool SaveStream( const ObjMesh& mesh , std::ostream& ost ) const;

protected:
	bool SaveObjMain( const ObjMesh& mesh , std::ostream& ost ) const;
};


}
