//==============================================================================
/*! \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:
 * - Extension of OpenMesh OMFormat for use in MDSTk Channel export
 * - Most of the code is modified OMFormat from OpenMesh
 */

#ifndef OM_FORMAT_EXT_HXX
#define OM_FORMAT_EXT_HXX


namespace OpenMesh {
namespace IO {

///////////////////////////////////////////////////////////////////////////////////////////
// Helper to store a an integer
// @param _os Output MDSTk channel
// @param _val Value to store
// @param _b Integer size
// @param _swap Swap byte flag
// @param t_signed Signed flag
// @return Number of saved bytes
///////////////////////////////////////////////////////////////////////////////////////////
template< typename T > size_t store( mds::mod::CChannel& _os, const T& _val, OMFormat::Chunk::Integer_Size _b, bool _swap, t_signed)
{    
    assert( OMFormat::is_integer( _val ) );

    switch( _b ) 
    {
		case OMFormat::Chunk::Integer_8:
		{ 	
			OMFormat::int8 v = static_cast<OMFormat::int8>(_val);
			return store( _os, v, _swap );
		}
		case OMFormat::Chunk::Integer_16:
		{ 
			OMFormat::int16 v = static_cast<OMFormat::int16>(_val);
			return store( _os, v, _swap );
		}
		case OMFormat::Chunk::Integer_32:
		{ 
			OMFormat::int32 v = static_cast<OMFormat::int32>(_val);
			return store( _os, v, _swap );
		}      
		case OMFormat::Chunk::Integer_64:
		{ 
			OMFormat::int64 v = static_cast<OMFormat::int64>(_val);
			return store( _os, v, _swap );
		}
	}
    return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////
// Helper to store a an unsigned integer
// @param _os Output MDSTk channel
// @param _val Value to store
// @param _b Integer size
// @param _swap Swap byte flag
// @param t_unsigned Unsigned flag
// @return Number of saved bytes
///////////////////////////////////////////////////////////////////////////////////////////
template< typename T > size_t store( mds::mod::CChannel& _os, const T& _val, OMFormat::Chunk::Integer_Size _b, bool _swap, t_unsigned)
{    
    assert( OMFormat::is_integer( _val ) );

    switch( _b ) 
    {
		case OMFormat::Chunk::Integer_8:
		{ 
			OMFormat::uint8 v = static_cast<OMFormat::uint8>(_val);
			return store( _os, v, _swap );
		}
		case OMFormat::Chunk::Integer_16:
		{ 
			OMFormat::uint16 v = static_cast<OMFormat::uint16>(_val);
			return store( _os, v, _swap );
		}
		case OMFormat::Chunk::Integer_32:
		{ 
			OMFormat::uint32 v = static_cast<OMFormat::uint32>(_val);
			return store( _os, v, _swap );
		}
        case OMFormat::Chunk::Integer_64:
		{ 
			OMFormat::uint64 v = static_cast<OMFormat::uint64>(_val);
			return store( _os, v, _swap );
		}
    }
    return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////
// Helper to restore a an integer
// @param _is Input MDSTk channel
// @param _val Value to restore
// @param _b Integer size
// @param _swap Swap byte flag
// @param t_signed Signed flag
// @return Number of restored bytes
///////////////////////////////////////////////////////////////////////////////////////////
template< typename T > size_t restore( mds::mod::CChannel& _is, T& _val, OMFormat::Chunk::Integer_Size _b, bool _swap, t_signed)
{    
    assert( OMFormat::is_integer( _val ) );
    size_t bytes = 0;

    switch( _b ) 
    {
		case OMFormat::Chunk::Integer_8:
		{ 	
			OMFormat::int8 v;
			bytes = restore( _is, v, _swap );
			_val = static_cast<T>(v);
			break;
		}
		case OMFormat::Chunk::Integer_16:
		{ 
			OMFormat::int16 v;
			bytes = restore( _is, v, _swap );
			_val = static_cast<T>(v);
		}
		case OMFormat::Chunk::Integer_32:
		{ 
			OMFormat::int32 v;
			bytes = restore( _is, v, _swap );
			_val = static_cast<T>(v);
		}      
		case OMFormat::Chunk::Integer_64:
		{ 
			OMFormat::int64 v;
			bytes = restore( _is, v, _swap );
			_val = static_cast<T>(v);
		}
	}
    return bytes;
}

///////////////////////////////////////////////////////////////////////////////////////////
// Helper to restore a an unsigned integer
// @param _is Input MDSTk channel
// @param _val Value to restore
// @param _b Integer size
// @param _swap Swap byte flag
// @param t_unsigned unsigned flag
// @return Number of restored bytes
///////////////////////////////////////////////////////////////////////////////////////////
template< typename T > size_t restore( mds::mod::CChannel& _is, T& _val, OMFormat::Chunk::Integer_Size _b, bool _swap, t_unsigned)
{    
    assert( OMFormat::is_integer( _val ) );
    size_t bytes = 0;

    switch( _b ) 
    {
		case OMFormat::Chunk::Integer_8:
		{ 
			OMFormat::uint8 v;
			bytes = restore( _is, v, _swap );
			_val = static_cast<T>(v);
			break;
		}
		case OMFormat::Chunk::Integer_16:
		{ 
			OMFormat::uint16 v;
			bytes = restore( _is, v, _swap );
			_val = static_cast<T>(v);
			break;
		}
		case OMFormat::Chunk::Integer_32:
		{ 
			OMFormat::uint32 v;
			bytes = restore( _is, v, _swap );
			_val = static_cast<T>(v);
			break;
		}
        case OMFormat::Chunk::Integer_64:
		{ 
			OMFormat::uint64 v;
			bytes = restore( _is, v, _swap );
			_val = static_cast<T>(v);
			break;
		}
    }
    return bytes;
}

} // namespace IO
} // namespace OpenMesh

#endif