/*****************************************************************************
 * $LastChangedDate: 2011-04-23 21:07:07 -0400 (Sat, 23 Apr 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Module configuration.
 *
 * Another subtle initiatialization problem:
 *
 * This was unusually put here in conf.cc instead of defs.hh.
 * namespace shader {
 * namespace defs {
 * osg::Vec3 DEFAULT_LIGHT0_POSITION(x,y,z);
 * } // namespace defs
 * } // namespace shader
 *
 * Conf::Conf( void )
 *    mLight0Position(shader::defs::DEFAULT_LIGHT0_POSITION)
 *
 * DEFAULT_LIGHT_POSITION might be initialized AFTER the Conf ctor executes!
 * So try to write only basic constants in defs if possible.
 *
 *//*
 * 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).
 *****************************************************************************/

#define SHADER_CONF_CC 1
#include <fstream>
#include "base/module.hh"
#include "base/conf.hh"
#include "base/conf_template_macros.hh"
#include "base/misc.hh"
#include "base/stream.hh"
using namespace base;
#include "math/module.hh"
#include "math/defs_vector.hh"
using namespace math;
#include "shader/module.hh"
#include "shader/conf.hh"
#include "shader/defs.hh"
#include <osg/Fog>

namespace shader {

////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////  Conf  ///////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

namespace global { Conf gConf; }

/*****************************************************************************
 * ctor/dtor.
 *****************************************************************************/
Conf::Conf( void )
:   mValid(false),
    // cmd-line args
    mEnableShaders(true),
    mEnableLighting(true),
    // .conf file
    mLight0Position(8000.0f, 10000.0f, 3000.0f),  // constants here solve
    mEnableFog(true),
    mFogColor(0.65f, 0.65f, 0.85f, 1.0f),         // initialization problem (see above)
    mFogDensity(0.0007),
    mFogMode(osg::Fog::EXP2),
    mFogMin(0.0f),
    mBrightness(1.0f)
    // Environment:
{
    // NOP
}

/*****************************************************************************
 * Initialize/read configuration.
 *****************************************************************************/
void
Conf::Init( const base::InitArgs& initArgs, const string& confTxtFilename )
{
    CONF_TEMPLATE_Init_ParseCmdline_ReadConfTxt;
}

/*****************************************************************************
 * Parse cmdline args.
 *****************************************************************************/
void
Conf::ParseCmdlineArgs( int argc, char** argv )
{
    // NOP
}

void
Conf::ParseCmdlineArgs2( int argc, char** argv )
{
    for ( int i = 1; i < argc; ++i )
    {
        if ( STRSTR( argv[i], "-no-shader" ) )  // or -no-shaders
        {
            // Disable shaders.
            mEnableShaders = false;
            CLOG << "Disabled shaders." << std::endl;
        }
        else if ( STRSTR( argv[i], "-no-light" ) )  // or -no-lights
        {
            // Disable lighting.
            mEnableLighting = false;
            CLOG << "Disabled lighting." << std::endl;
        }
        else if ( STREQ( argv[i], "-no-fog" ) )
        {
            mEnableFog = false;
            CLOG << "Disabled fog." << std::endl;
        }
        else if ( STREQ( argv[i], "-brightness" ) )
        {
            mBrightness = Argf( i+1, argc, argv );
        }
    }
}

/*****************************************************************************
 * Read from .conf file.
 *****************************************************************************/
void
Conf::ReadConfTxt( const string& confTxtFilename )
{
    CONF_TEMPLATE_ReadConfTxt;
}

void
Conf::ModuleConfTxt::ProcessField( string& field, std::ifstream& conf )
{
    bool error = false;

    //---------------------  light  ---------------------------------------------
    if ( field == "Light0Position" )
    {
        conf >> SHADER_CONF.mLight0Position[XX];
        conf >> SHADER_CONF.mLight0Position[YY];
        conf >> SHADER_CONF.mLight0Position[ZZ];
    }
    //---------------------  fog  ---------------------------------------------
    else if ( field == "FogColor" )
    {
        fp r, g, b, a;
        conf >> r;
        conf >> g;
        conf >> b;
        conf >> a;
        SHADER_CONF.mFogColor.Set( r, g, b, a );
    }
    else if ( field == "FogMode" )
    {
        string s; conf >> s;  // string
        if ( s == "linear" )
        {
            SHADER_CONF.mFogMode = osg::Fog::LINEAR;
        }
        else if ( s == "exp2" )
        {
            SHADER_CONF.mFogMode = osg::Fog::EXP2;
        }
        else  // default
        {
            error = (s != "exp");
            SHADER_CONF.mFogMode = osg::Fog::EXP;
        }
    }
    else if ( field == "FogDensity" )
    {
        conf >> SHADER_CONF.mFogDensity;
    }
    else if ( field == "FogMin" )
    {
        conf >> SHADER_CONF.mFogMin;
    }
    
    // Errors?
    if ( error )
    {
        CERROR << "ERROR[conf]: parameter for " << field << " is invalid." << std::endl;
        EXIT( 1 );
    }
}

/*****************************************************************************
 * Print Conf configuration.
 *****************************************************************************/
std::ostream& operator<<( std::ostream& strm, const Conf& conf )
{
    std::ios::fmtflags savedFlags = strm.flags();

    strm << "conf [shader]:"                                                      << std::endl
         << "enable shaders              = " << conf.mEnableShaders            ;//<< std::endl
    strm.flags(savedFlags);

    return strm;
}

} // namespace shader
