/*****************************************************************************
 * $LastChangedDate: 2011-04-23 21:07:07 -0400 (Sat, 23 Apr 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Functions that extend ConfBin.
 *//*
 * LEGAL:   COPYRIGHT (C) 2008 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#define GLUE_CONF_BIN_EXT_CC 1
#include "base/module.hh"
#include "base/stream.hh"
using namespace base;
#include "math/module.hh"
#include "math/matrix.hh"
using namespace math;
#include "glue/module.hh"
#include "glue/conf_bin_ext.hh"
#include "glue/conf.hh"

namespace glue {

/*****************************************************************************
 * Open the binary configuration file (~/.PROGRAM_NAME.cfg).
 *****************************************************************************/
ConfBin&
GetConfBin( void )
{
    PERSISTENT ConfBin* sConfBin = NULL;  // binary .cfg file

    if ( EX( sConfBin != NULL ) )
    {
        return *sConfBin;
    }
    else
    {
        try
        {
            ASSERT( GLUE_CONF.mProgramName != "" );
            sConfBin = new base::ConfBin( GLUE_CONF.mProgramName, "", ConfBin::AUTO_FLUSH );
        }
        catch (...)
        {
            CERROR << "ERROR: Cannot open binary .cfg file" << std::endl;
            EXIT(1);
        }

        return *sConfBin;
    }
}

/*****************************************************************************
 * Read a single-precision float.
 *****************************************************************************/
bool
ReadConfBin( ConfBin& confBin, const string& key, fp& out )
{
    double d;
    const bool res = confBin.Read( key, d );
    out = fp(d);  // lost precision
    return res;
}

/*****************************************************************************
 * Read Vector3 from binary configuration.
 *****************************************************************************/
bool
ReadConfBin( ConfBin& confBin, const string& key, Vector3& v )
{
    return ReadConfBin( confBin, key + string("_x"), v[XX] )
       and ReadConfBin( confBin, key + string("_y"), v[YY] )
       and ReadConfBin( confBin, key + string("_z"), v[ZZ] );
}

/*****************************************************************************
 * Write Vector3 to binary configuration.
 *****************************************************************************/
bool
WriteConfBin( ConfBin& confBin, const string& key, const Vector3& v )
{
    return confBin.Write( key + string("_x"), double(v[XX]) )
       and confBin.Write( key + string("_y"), double(v[YY]) )
       and confBin.Write( key + string("_z"), double(v[ZZ]) );
}

/*****************************************************************************
 * Read Matrix from binary configuration.
 *****************************************************************************/
bool
ReadConfBin( ConfBin& confBin, const string& key, Matrix& matrix /*OUT*/ )
{
    // Matrix is single-precision, but ConfBin method only provides a double,
    // so use the external function ReadConfBin(fp).
    return ReadConfBin( confBin, key + string("_Xx"), matrix[Xx] )
       and ReadConfBin( confBin, key + string("_Xy"), matrix[Xy] )
       and ReadConfBin( confBin, key + string("_Xz"), matrix[Xz] )
       and ReadConfBin( confBin, key + string("_Xw"), matrix[Xw] )
       and ReadConfBin( confBin, key + string("_Yx"), matrix[Yx] )
       and ReadConfBin( confBin, key + string("_Yy"), matrix[Yy] )
       and ReadConfBin( confBin, key + string("_Yz"), matrix[Yz] )
       and ReadConfBin( confBin, key + string("_Yw"), matrix[Yw] )
       and ReadConfBin( confBin, key + string("_Zx"), matrix[Zx] )
       and ReadConfBin( confBin, key + string("_Zy"), matrix[Zy] )
       and ReadConfBin( confBin, key + string("_Zz"), matrix[Zz] )
       and ReadConfBin( confBin, key + string("_Zw"), matrix[Zw] )
       and ReadConfBin( confBin, key + string("_Ox"), matrix[Ox] )
       and ReadConfBin( confBin, key + string("_Oy"), matrix[Oy] )
       and ReadConfBin( confBin, key + string("_Oz"), matrix[Oz] )
       and ReadConfBin( confBin, key + string("_Ow"), matrix[Ow] );
}

/*****************************************************************************
 * Write Matrix to binary configuration.
 *****************************************************************************/
bool
WriteConfBin( ConfBin& confBin, const string& key, const Matrix& matrix )
{
    return confBin.Write( key + string("_Xx"), double(matrix[Xx]) )
       and confBin.Write( key + string("_Xy"), double(matrix[Xy]) )
       and confBin.Write( key + string("_Xz"), double(matrix[Xz]) )
       and confBin.Write( key + string("_Xw"), double(matrix[Xw]) )
       and confBin.Write( key + string("_Yx"), double(matrix[Yx]) )
       and confBin.Write( key + string("_Yy"), double(matrix[Yy]) )
       and confBin.Write( key + string("_Yz"), double(matrix[Yz]) )
       and confBin.Write( key + string("_Yw"), double(matrix[Yw]) )
       and confBin.Write( key + string("_Zx"), double(matrix[Zx]) )
       and confBin.Write( key + string("_Zy"), double(matrix[Zy]) )
       and confBin.Write( key + string("_Zz"), double(matrix[Zz]) )
       and confBin.Write( key + string("_Zw"), double(matrix[Zw]) )
       and confBin.Write( key + string("_Ox"), double(matrix[Ox]) )
       and confBin.Write( key + string("_Oy"), double(matrix[Oy]) )
       and confBin.Write( key + string("_Oz"), double(matrix[Oz]) )
       and confBin.Write( key + string("_Ow"), double(matrix[Ow]) );
}

} // namespace glue
