/*****************************************************************************
 * $Id: mod_pony_init.cc,v 1.2 2006/11/25 17:36:46 devel Exp $
 * @file
 * @author	Jim E. Brooks  http://www.jimbrooks.org
 * @brief	Initialization.
 *//*
 * LEGAL:	COPYRIGHT (C) 2004 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE (GPL).
 *****************************************************************************/

#define MOD_PONY_INIT_CC 1
#include "mod_pony_common.hh"
#include "mod_pony_init.hh"
#include "mod_pony_world.hh"
#include "mod_pony_terrain.hh"
#include "mod_pony_gui.hh"
#include "mod_base_craft.hh"

// Globals (major objects).
ModulePony		gModule;
ModulePonyWorld gWorld;

/*****************************************************************************
 * main.
 *****************************************************************************/
int
main( int argc, char** argv )
{
	return gModule.Init( argc, argv, "palomino" );
}

/*****************************************************************************
 * Initialize.
 * @return 0 if successful (UNIX exit convention).
 *****************************************************************************/
int
ModulePony::Init( int argc, char** argv, const string& appname )
{
					///////////////////////////
					// ENGINE IS NOT READY!! //
					///////////////////////////

	// Some initialization must be done before cmd-line args are processed
	// in order to let them override default settings.  By contrast, some
	// initialization depends on cmd-line args (eg argv[0]).

	StartStopListeners( true );

	Parent::Init( argc, argv, appname );

	// - - - - - - override base member default values - - - - - - - - - - - - -
	//mCollisions	= true;			// wrong, use EnableCollisions() which informs engine
	EnableCollisions( true );		// default, base class
	mTexturing		= true;			// default, base class
	mDemoMode		= false;		// default, base class
	// - - - - - - override base member default values - - - - - - - - - - - - -

	mDefaultFogDensity	= 0.5;

	Cmdarg( argc, argv );

	// Depends on mPlayer being initialized.
	LoadState();

	// Find paths to textures, models, and Python files.
	// First try relative to src dir, second try UNIX installation path.
	const string moduleDir = "../modules/pony/";  // HARDCODE
	const string installDir = GetInstallDir( PROGRAM_EXEC_STR, argv );
    const string unixInstallDir = "/usr/share/games/palomino/";  // HARDCODE UNIX installation path
	mTextureDirVec.push_back( installDir + moduleDir + string("/textures/" ) );
	mTextureDirVec.push_back( unixInstallDir );
	mModelDir = installDir + moduleDir + string("/models/");
    if ( ! IfDirExists( mModelDir ) )  // .pal files
    {
    	mModelDir = unixInstallDir;  // last try UNIX installation dir
        if ( ! IfDirExists( mModelDir ) )
        {
            *gStreamError << "ERROR: Cannot find 3D model files (*.pal)" << endl;
			gEng.Exit(1);
        }
    }
#ifndef NO_PYTHON
	mPythonDir = installDir + moduleDir + string("/out/");  // HARDCODE
    if ( ! IfDirExists( mPythonDir ) )  // .py files
    {
        mPythonDir = unixInstallDir;
        if ( ! IfDirExists( mPythonDir ) )
        {
            *gStreamError << "ERROR: Cannot file Python files (*.py)" << endl;
			gEng.Exit(1);
        }
    }
#endif

    // HARDCODE until there's a terrain height database.
    mAltitudeLand  = GROUND_LEVEL - WORLD(25.0);
    mAltitudeWater = GROUND_LEVEL - WORLD(5.0);

	gEng.Init( argc, argv, mDefaultWindowWidth, mDefaultWindowHeight );

	return 0;
}

/*****************************************************************************
 * Process command-line args.
 *****************************************************************************/
void
ModulePony::Cmdarg( int argc, char** argv )
{
	// Call base class which processes common args.
	Parent::Cmdarg( argc, argv );

	// Parse args.
	for ( int i = 1; i < argc; ++i )
	{
		// Help?
		if (    STREQ( argv[i], "--help" )
             || STREQ( argv[i], "-help"  )
             || STREQ( argv[i], "-h"     )
             || STREQ( argv[i], "/?"     )
             || STREQ( argv[i], "/h"     ) )
		{
			PrintHelpConsole();
			gEng.Exit(0);
		}
		// Easter egg?
		else if (    STREQ( argv[i], "-easter" )
                  || STREQ( argv[i], "-egg" )
                  || STREQ( argv[i], "-underdog" ) )
		{
			mCmdarg.mEasterEgg = true;
			Underdog();
			CmdargDone( i );
		}
		// Load saved view? (saved view and the other saved config state are different notions)
		else if ( STREQ( argv[i], "-view" ) )
		{
			mCmdarg.mReloadView = true;
			CmdargDone( i );
		}
		else if ( STREQ( argv[i], "-noconfig" ) || STREQ( argv[i], "-no-config" ) )
		{
			mCmdarg.mNoReload = true;
			CmdargDone( i );
		}
		// Demo mode?
		else if ( STREQ( argv[i], "-demo" ) )
		{
			mCmdarg.mDemo = true;
			CmdargDone( i );
		}
		// Game mode?
		else if ( STREQ( argv[i], "-game" ) )
		{
			mCmdarg.mGame = true;
			CmdargDone( i );
		}
		// Terrain: verdant/desert?
		else if ( STREQ( argv[i], "-verdant" ) )
		{
			gWorldParm.mTerrain.mDesert = false;
			CmdargDone( i );
		}
		else if ( STREQ( argv[i], "-desert" ) )
		{
			gWorldParm.mTerrain.mDesert = true;
			CmdargDone( i );
		}
		// Terrain: hills or mountains?
		else if ( STREQ( argv[i], "-hills" ) )
		{
			gWorldParm.mTerrain.mMountains = eTerrainParmMountains_ROLLING_HILLS;
			CmdargDone( i );
		}
		else if ( STREQ( argv[i], "-mountains" ) )
		{
			gWorldParm.mTerrain.mMountains = eTerrainParmMountains_NORMAL;
			CmdargDone( i );
		}
		else if ( STREQ( argv[i], "-mountains=huge" ) || STREQ( argv[i], "-mountains-huge" ) )
		{
			gWorldParm.mTerrain.mMountains = eTerrainParmMountains_HUGE;
			CmdargDone( i );
		}
		// Trees.
		// -tree-density 0.0 is equivalent to -no-trees.
		else if ( STREQ( argv[i], "-no-trees" ) )
		{
			gWorldParm.mTree.mDisable = true;
			CmdargDone( i );
		}
		else if ( STREQ( argv[i], "-tree-density" ) )
		{
			mCmdarg.mTreeDensity = true;
			gWorldParm.mTree.mDensity = Min<fp>(20.0,Argf(i+1,argc,argv));
			if ( gWorldParm.mTree.mDensity < 0.01 ) gWorldParm.mTree.mDisable = true;
			CmdargDone( i, 2 );
			i += 1;					// note the order: CmdargDone() before incrementing i
		}
		// Hill/mountain density per quadrant.
		else if ( STREQ( argv[i], "-hill-density" )
               || STREQ( argv[i], "-mountain-density" ) )
		{
			mCmdarg.mHillDensity = true;
			gWorldParm.mHill.mDensity = Argf(i+1,argc,argv);
			CmdargDone( i, 2 );
			i += 1;
		}
		// Water parameters.
		else if ( STREQ( argv[i], "-water-density" ) )
		{
			gWorldParm.mWater.mDensity = Argf(i+1,argc,argv);
			CmdargDone( i, 2 );
			i += 1;
		}
		// Fog parameters.
		else if ( STREQ( argv[i], "-fog-density" ) )
		{
			mCmdarg.mFogDensity = true;
			fp fogDensity = Argf(i+1,argc,argv);
			gEng.SetFogDensity( fogDensity );
			CmdargDone( i, 2 );
			i += 1;
		}
		else if ( STREQ( argv[i], "-cloud-density" ) )
		{
			mCmdarg.mCloudDensity = true;
			gWorldParm.mCloud.mDensity = Argf(i+1,argc,argv);
			CmdargDone( i, 2 );
			i += 1;
		}
		else if ( STREQ( argv[i], "-sunset" ) )
		{
			mCmdarg.mSunset = true;
			mWeather.SetTime( Weather::eTime_SUNSET );
			CmdargDone( i );
		}
#if 0 // obsolete
		else if ( STREQ( argv[i], "-fog-quality" ) )
		{
			int fogQuality = Argi(i+1,argc,argv);
			gEng.SetFogQuality( fogQuality );
			CmdargDone( i, 2 );
			i += 1;
		}
#endif	// Size of the world.
		else if ( STREQ( argv[i], "-world=normal" ) )
		{
			gWorldParm.mWorldSize = eWorldSize_NORMAL;
			CmdargDone( i );
		}
		else if ( STREQ( argv[i], "-world=large" ) )
		{
			gWorldParm.mWorldSize = eWorldSize_LARGE;
			CmdargDone( i );
		}
		else if ( STREQ( argv[i], "-world=huge" ) )
		{
			gWorldParm.mWorldSize = eWorldSize_HUGE;
			CmdargDone( i );
		}
		// GUI zoom.
		else if ( STREQ( argv[i], "-gui-zoom" ) || STREQ( argv[i], "-guizoom" ) )
		{
			mCmdarg.mGuiZoom = true;
			float zoom = Argf(i+1,argc,argv);
			zoom = MIN( zoom, 3.0 );
			gGui.SetZoom( zoom ); // yes, can be called even though Gui object not init-ed
			CmdargDone( i, 2 );
			i += 1;
		}
		// Rude/polite.
		else if ( STREQ( argv[i], "-rude" ) )
		{
			mCmdarg.mRude = true;
			CmdargDone( i );
		}
		else if ( STREQ( argv[i], "-polite" ) )
		{
			mCmdarg.mRude = false;
			CmdargDone( i );
		}
	}
}

/*****************************************************************************
 * Help.
 *****************************************************************************/
static void
PrintHelpConsole( void )
{
	Splash();
	*gStreamOut << "See " WEBSITE_STR "/manual.html" << endl;
}

/*****************************************************************************
 * Startup splash screen.
 *****************************************************************************/
static void
SplashHeader( void )
{
	*gStreamOut << "\n"
    "============================================\n"
    PROGRAM_LONG_NAME_STR " - " MODULE_NAME_STR " module \n"
    COPYRIGHT_STR " " AUTHORS_STR " - " WEBSITE_STR "\n"
	"============================================" << endl;
#ifdef __CYGWIN__
    // KLUDGE (2006/06) closing window on cygwin causes hang so tell user not to do it.
    *gStreamOut << "\nNOTE:\nEXIT PROGRAM USING CTRL+C.\nDON'T CLOSE WINDOW OR PROCESS WILL HANG (cygwin issue)\n\n";
#endif
}
void
Splash( void )
{
	SplashHeader();
}

/*****************************************************************************
 * Easter egg.
 *****************************************************************************/
static void
Underdog( void )
{
	*gStreamOut <<
    "------------------------------------------------------------------------------\n"
    " Look!  Up in the sky!  It's a bird!  It's a plane! \n"
    " No, it's Underdog! \n"
    "                                    ,.+----.\n"
    "                               ,*''         I\n"
    "              ____           /         Mbp. dP          __\n"
    "          ,o@QBBBBBbm,_     ; ,d       /~`QMP'\\     _odBBBBbo,\n"
    "          OBBROYALBBBBBBBBmOBBBM      |    |   |,*~dBBBBBBBBBBBb \n"
    "          OBBBBBBBBBBqBBBBBBBBBP      |  0 |0 ,'  dBBBBBBBBBBBBBb\n"
    "          '*BBBP'     ^OBBBP'          \\__/  ~    OBBBBBBBBBBBBBP\n"
    "      /                     :           __.       `0BBBBBBBBBBP|\n"
    "                    .-.     `          ~,A.         `0BBBBBBBBP |\n"
    "                 .-(   `x__  `\\        .B*Bb          `'?OOP~   ;\n"
    "              .-(   `\\/'   `.  `~--++*\\{  `Pb           ,'     ,'\n"
    "   /         (   `\\_/'\\__/  )     _    !`-' !`.       ,'     ,'  \n"
    "        /     `\\_/'       ,'     L '+,_|    |-,`.__ ,'    _,','~~\\.~~~\\\n"
    "                 \\        /\\    / ',   '+.  |/ >   `~~~~~~  ,'    :/~  \\\n"
    "    /             `~===\\/'  `\\/'    '+.   >{  /\\        __.,: |   ;    ;\n"
    "           /           {         ,|    `\\/  \\/  `Y~~---~   `. `--:'~~~';\n"
    "                        `\\     ,&#|    uuu    uuu \\         `,   ;^`~~';\n"
    "        /               ,d#b,.&###|    UUU.   UUU. `\\     __.;~~' `~~~'\n"
    "      /              ,d###########|    UUU;   |UU:   Y~~~~\n"
    "                 ,d############i~      `UUUUUUUUU;   I  \n"
    "           ,d##################I        `UUUUUUU'    I     /   /\n"
    " (#############################b.                    Im \n"
    "    )############################b.      \\           d#b\n"
    "   (###############################b++g+++~#b      ,d##P\n"
    "       }####################P~ ~Y####P    J#P`~~~T'\n"
    "      (###################P'     `YP'    ;P'   ,'\n"
    "        )###############P'        '    ,'    ,'    /\n"
    "       (##############P'          __+~'   /##'\n"
    "  /            Y####P'         ;-'     /###P\n"
    "            /   Y#P'         /'      /&##P~\n"
    "                 |         /'      /&#P~         \n"
    "      /          `\\______/'\\_____/'            \n"
    "                                    /            \n"
    "                           /\n"
    "              /                          \n"
    "------------------------------------------------------------------------------"
	<< endl;
}
