/*****************************************************************************
 * $LastChangedDate: 2011-08-20 12:07:38 -0400 (Sat, 20 Aug 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Module configuration.
 *//*
 * LEGAL:   COPYRIGHT (C) 2007 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#define VIEW_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"
#include "base/stream_funcs.hh"
using namespace base;
#include "math/module.hh"
#include "math/defs_trig.hh"
#include "math/funcs_trig.hh"
using namespace math;
#include "gfx/module.hh"
#include "gfx/rgba.hh"
using namespace gfx;
#include "view/module.hh"
#include "view/conf.hh"

namespace view {

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

namespace global { Conf gConf; }

/*****************************************************************************
 * ctor/dtor.
 *****************************************************************************/
Conf::Conf( void )
:   mValid(false),
    // cmd-line args 
    // (none)
    // .conf file
    mWindowTitle(""),
    mWindowPosition(64,64),
    mWindowWidthHeight(800,600),
    mViewProjectionFOV(55.0),  // fpx
    mViewProjectionAspectRatio(1.10), // fpx
    mViewNearFarRatio(0.0002),  // fpx
    mOtwViewpointOffset(0.0f),
    mStatsEnabled(true),
    mManipulatorEnabled(false),
    mManipulatorYawRad(math::RADIAN_1),
    mManipulatorPitchRad(math::RADIAN_1),
    mManipulatorStep(10.0f),
    mManipulatorPosition(0,0,0),
    mManipulatorRotationList()
{
}

/*****************************************************************************
 * 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 )
{
    // Parse cmd-line args.
    for ( int i = 1; i < argc; ++i )
    {
        if ( STREQ( argv[i], "-wh" )
          or STREQ( argv[i], "-window" ) )
        {
            mWindowWidthHeight.w = Argi( i+1, argc, argv );
            mWindowWidthHeight.h = Argi( i+2, argc, argv );
            CmdargDone( i, 2 );
            CLOG << "Set window size " << mWindowWidthHeight << '.' << std::endl;
        }
        else if ( STREQ( argv[i], "-t" ) )  // arg's name is legacy from OSG trackball manipulator
        {
            mManipulatorEnabled = true;
            CLOG << "Enabled manipulator mode." << std::endl;
        }
        else if ( STREQ( argv[i], "-no-stats" )
             /* or STREQ( argv[i], "-fast" ) */ )
        {
            // OSG statistics possibly could cause inteference.
            // -stats is omitted, rather, press F12 key.
            mStatsEnabled = false;
            CLOG << "Disabled OSG stats." << std::endl;
        }
    }
}

/*****************************************************************************
 * 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;

    if ( field == "WindowTitle" )
    {
        StreamReadLine( conf, VIEW_CONF.mWindowTitle );
    }
    else if ( field == "WindowWidth" )
    {
        conf >> VIEW_CONF.mWindowWidthHeight.w;
    }
    else if ( field == "WindowHeight" )
    {
        conf >> VIEW_CONF.mWindowWidthHeight.h;
    }
    else if ( field == "ViewProjectionFOV" )
    {
        conf >> VIEW_CONF.mViewProjectionFOV;
    }
    else if ( field == "ViewProjectionAspectRatio" )
    {
        conf >> VIEW_CONF.mViewProjectionAspectRatio;
    }
    else if ( field == "ViewNearFarRatio" )
    {
        conf >> VIEW_CONF.mViewNearFarRatio;
    }
    else if ( field == "OtwViewpointOffset" )
    {
        conf >> VIEW_CONF.mOtwViewpointOffset;  // raw world coordinate (height)
    }
    else if ( field == "ManipulatorYaw" )
    {
        fp deg; conf >> deg;
        VIEW_CONF.mManipulatorYawRad = Deg2Rad( Degree(deg) );
    }
    else if ( field == "ManipulatorPitch" )
    {
        fp deg; conf >> deg;
        VIEW_CONF.mManipulatorPitchRad = Deg2Rad( Degree(deg) );
    }
    else if ( field == "ManipulatorStep" )
    {
        conf >> VIEW_CONF.mManipulatorStep;
    }
    else if ( field == "ManipulatorPosition" )
    {
        conf >> VIEW_CONF.mManipulatorPosition[XX];
        conf >> VIEW_CONF.mManipulatorPosition[YY];
        conf >> VIEW_CONF.mManipulatorPosition[ZZ];
    }
    else if ( field == "ManipulatorRotationList" )
    {
        VIEW_CONF.mManipulatorRotationList.Parse( conf );
    }

    // 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 [view]:"                                              << std::endl
         << "WindowWidth,Height          = " << conf.mWindowWidthHeight; //std::endl
    strm.flags(savedFlags);

    return strm;
}

} // namespace view
