/*****************************************************************************
 * $LastChangedDate: 2010-05-02 15:12:55 -0400 (Sun, 02 May 2010) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Macros to simplify glue code between C++ and Lua (program-specific).
 * @remarks See macros.hh
 *//*
 * LEGAL:   COPYRIGHT (C) 2009 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

// Avoid lua_/LUA_ which is reserved by Lua.

#ifndef LUABIND_MACROS_PROGRAM_HH
#define LUABIND_MACROS_PROGRAM_HH 1

#include "math/module.hh"
#include "math/matrix.hh"
using namespace math;
#include "gfx/rgba.hh"
#include "gfx/graphics.hh"
using namespace gfx;
#include "physics/types.hh"
using namespace physics;

namespace lua {
namespace bind {

// Pop RGBA (Lua pushes 4 fp).
RGBA
POP_RGBA( lua_State* L );

// Pop Lua table into Rect<int>.
Rect<int>
POP_TABLE_INTO_RECT( lua_State* L );

/// Pop a 3D vector as either x,y,z or {[0]=x,[1]=y,[2]=z}.
/// The Lua scripts define the class Vec3 which
/// is a table with index starting at ZERO (0).
template<typename VECTOR3>
VECTOR3
POP_VECTOR3( lua_State* L )
{
    // This gross template code supports GeoVertex(Meter,Meter,Meter) though.
    if ( EX( IF_TABLE( L, -1 ) ) )
    {
        typename VECTOR3::value_type x = typename VECTOR3::value_type( GET_MEMBER_AS_NUMBER( L, int(XX) ) );
        typename VECTOR3::value_type y = typename VECTOR3::value_type( GET_MEMBER_AS_NUMBER( L, int(YY) ) );
        typename VECTOR3::value_type z = typename VECTOR3::value_type( GET_MEMBER_AS_NUMBER( L, int(ZZ) ) );
        lua_pop( L, 1 );  // pop Vec3 table
        return VECTOR3( x, y, z );  // ZERO-BASED
    }
    else
    {
        // Pop in reverse.
        typename VECTOR3::value_type z = typename VECTOR3::value_type( POP_FP( L ) );
        typename VECTOR3::value_type y = typename VECTOR3::value_type( POP_FP( L ) );
        typename VECTOR3::value_type x = typename VECTOR3::value_type( POP_FP( L ) );
        return VECTOR3( x, y, z );  // ZERO-BASED
    }
}

// Pop SphereVertex (heterogenous members).
#if COMPILE_PALOMINO
SphereVertex
POP_SPHERE_VERTEX( lua_State* L );
#endif // COMPILE_PALOMINO

/// Push a 3D vector as table {[0]=x,[1]=y,[2]=z} with index starting at ZERO (0).
template<typename VECTOR3>
void
PUSH_VECTOR3( lua_State* L, const VECTOR3& v )
{
    lua_newtable( L );
    SET_MEMBER_AS_NUMBER( L, int(XX), v[XX] );  // ZERO-BASED
    SET_MEMBER_AS_NUMBER( L, int(YY), v[YY] );  // int() because template requires exact arg types
    SET_MEMBER_AS_NUMBER( L, int(ZZ), v[ZZ] );
}

// Push a spherical vertex as table with index starting at ZERO (0).
#if COMPILE_PALOMINO
void
PUSH_SPHERE_VERTEX( lua_State* L, const SphereVertex& sv );
#endif // COMPILE_PALOMINO

// Pop a table containing a 4x4 matrix.
void
POP_TABLE_INTO_MATRIX( lua_State* L, Matrix& matrix/*OUT*/ );

// Push a table containing a 4x4 matrix.
void
PUSH_TABLE_FROM_MATRIX( lua_State* L, const Matrix& matrix );

} // namespace bind
} // namespace lua

#endif // LUABIND_MACROS_PROGRAM_HH
