//==============================================================================
/*! \file
 * OpenMesh Toolkit for mesh analysis    \n
 * Copyright (c) 2010 by Rostislav Hulik     \n
 *
 * Author:  Rostislav Hulik, rosta.hulik@gmail.com  \n
 * Date:    2010/10/20                          \n
 *
 * This file is part of software developed for support of Rostislav Hulik's dissertation thesis at dcgm-robotics@FIT group.
 *
 * This file is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This file 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this file.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Description:
 * - Helper methods for easy export/import of models through several channels
 */

#ifndef _OM_IO_H_
#define _OM_IO_H_

#include <OMToolkit\IO\OMWriterExt.h>
#include <OMToolkit\IO\OMReaderExt.h>
#include <OpenMesh\Core\IO\MeshIO.hh>

namespace OMToolkit {
namespace IO {

/**
 * Helper type forr specifying r/w options
 */
typedef OpenMesh::IO::Options Options;

/**
 * Method writes a mesh into MDSTk input channel
 * Automaticaly sets persistency od original auxiliary data
 * If user wants to save his custom properties too, it must be saved as persistent property
 * @param mesh Mesh to store
 * @param channel MDSTk input channel
 * @param opt Options for reading (for binary/ascii specification etc.)
 * @return True, if writing was done successfully
 */
template <class Mesh>
static bool writeMesh(Mesh &mesh, mds::mod::CChannel& channel, Options opt = Options::Default);

/**
 * Method writes a mesh into file specified by filename (format is determined from filename)
 * Possible formats are STL, OFF, OM, OBJ, PLY
 * Automaticaly sets persistency od original auxiliary data
 * If user wants to save his custom properties too, it must be saved as persistent property
 * @param mesh Mesh to store
 * @param filename File name 
 * @param opt Options for reading (for binary/ascii specification etc.)
 * @return True, if writing was done successfully
 */
template <class Mesh>
	static bool writeMesh(Mesh &mesh, std::string filename, Options opt = Options::Default);

/**
 * Method writes a mesh into STL output stream
 * Possible formats are STL, OFF, OM, OBJ, PLY
 * Automaticaly sets persistency od original auxiliary data
 * If user wants to save his custom properties too, it must be saved as persistent property
 * @param mesh Mesh to store
 * @param stream Stream where a mesh will be stored
 * @param format Format specification - for ex. ".OM"
 * @param opt Options for reading (for binary/ascii specification etc.)
 * @return True, if writing was done successfully
 */
template <class Mesh>
	static bool writeMesh(Mesh &mesh, std::ostream& stream, std::string format, Options opt = Options::Default);

/**
 * Method reads a mesh from MDSTk input channel
 * Automaticaly reads all available data
 * @param mesh Destination mesh
 * @param channel MDSTk output channel
 * @param opt Options for reading (for binary/ascii specification etc.)
 * @return True, if reading was done successfully
 */
template <class Mesh>
	static bool readMesh(Mesh &mesh, mds::mod::CChannel& channel, Options& opt);

/**
 * Method reads a mesh from a file specified by filename (format is determined from filename)
 * Possible formats are STL, OFF, OM, OBJ, PLY
 * @param mesh Destination mesh
 * @param filename File name 
 * @param opt Options for reading (for binary/ascii specification etc.)
 * @return True, if reading was done successfully
 */
template <class Mesh>
	static bool readMesh(Mesh &mesh, std::string filename, Options& opt);

/**
 * Method writes a mesh from a STL input stream
 * Possible formats are STL, OFF, OM, OBJ, PLY
 * @param mesh Destination mesh
 * @param stream Source stream
 * @param format Format specification - for ex. ".OM"
 * @param opt Options for reading (for binary/ascii specification etc.)
 * @return True, if reading was done successfully
 */
template <class Mesh>
	static bool readMesh(Mesh &mesh, std::istream& stream, std::string format, Options& opt);

/**
 * Method exports a mesh vertices into dense 2D array
 *		format of each line: Vx Vy Vz [Nx] [Ny] [Nz]
 *		V(x,y,z) are coordinates of each vertex 
 *		N(x,y,z) are coordinates of surface normal on vertex (arbitrary)
 * ARRAY MUST BE INITIALIZED 
 *		size = (num_vertices * 3 * sizeof(Scalar)) in case of normals == false
 *		size = (num_vertices * 6 * sizeof(Scalar)) in case of normals == true
 * @tparam Mesh Input mesh type
 * @tparam Scalar Output array type
 * @param mesh Source mesh
 * @param output_array Output array of Scalar type
 * @param normals Should be normals added into output mesh?
 * @return True, if writing was done successfully
 */
template <class Mesh, typename Scalar>
	static bool exportVertices(Mesh &mesh, Scalar *output_array, bool normals = false);

/**
 * Method exports a mesh faces into dense 2D array
 *		format of each line: Vid1 Vid2 Vid3
 *		VidX are indices of each vertex 
 * ARRAY MUST BE INITIALIZED 
 *		size = (num_faces * 3 * sizeof(int))
 * @tparam Mesh Input mesh type
 * @param mesh Source mesh
 * @param output_array Output array of int type
 * @return True, if writing was done successfully
 */
template <class Mesh>
	static bool exportFaces(Mesh &mesh, int *output_array);

/**
 * Method imports mesh vertices from dense 2D array
 *		format of each line: Vx Vy Vz [Nx] [Ny] [Nz]
 *		V(x,y,z) are coordinates of each vertex 
 *		N(x,y,z) are coordinates of surface normal on vertex (arbitrary)
 * @tparam Mesh Output mesh type
 * @tparam Scalar Intput array type
 * @param mesh Destination mesh
 * @param input_array Input array of Scalar type
 * @param size Number of vertices
 * @param normals Should be normals added into output mesh?
 * @return True, if reading was done successfully
 */
template <class Mesh, typename Scalar>
	static bool importVertices(Mesh &mesh, Scalar *input_array, int size, bool normals = false);

/**
 * Method imports mesh faces from dense 2D array
 *		format of each line: Vid1 Vid2 Vid3
 *		VidX are indices of each vertex 
 * @tparam Mesh Output mesh type
 * @param mesh Output mesh
 * @param input_array Input array of int type
 * @param size Number of faces
 * @return True, if reading was done successfully
 */
template <class Mesh>
	static bool importFaces(Mesh &mesh, int *input_array, int size);

} // namespace IO
} // namespace OMToolkit

#include <OMToolkit/IO\OMIO.hxx>

#endif