//   ___________		     _________		      _____  __
//   \_	  _____/______   ____   ____ \_   ___ \____________ _/ ____\/  |_
//    |    __) \_  __ \_/ __ \_/ __ \/    \  \/\_  __ \__  \\   __\\   __\ 
//    |     \   |  | \/\  ___/\  ___/\     \____|  | \// __ \|  |   |  |
//    \___  /   |__|    \___  >\___  >\______  /|__|  (____  /__|   |__|
//	  \/		    \/	   \/	     \/		   \/
//  ______________________                           ______________________
//			  T H E   W A R   B E G I N S
//	   FreeCraft - A free fantasy real time strategy game engine
//
/**@name clone.c	-	The main file. */
/*
**	(c) Copyright 1998-2000 by Lutz Sammer
**
**	$Id: clone.c,v 1.24 2000/08/13 13:01:09 johns Exp $
*/

//@{

/*----------------------------------------------------------------------------
--	Includes
----------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>

#ifdef USE_BEOS
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#endif

#ifdef __CYGWIN__
#include <getopt.h>
#endif

#ifdef __MINGW32__
#include <SDL/SDL.h>
extern int opterr;
extern int optind;
extern int optopt;
extern char *optarg;

extern int getopt(int argc, char *const*argv, const char *opt);
#endif

#include "freecraft.h"

#include "video.h"
#include "image.h"
#include "tileset.h"
#include "map.h"
#include "minimap.h"
#include "sound_id.h"
#include "unitsound.h"
#include "icons.h"
#include "button.h"
#include "unittype.h"
#include "player.h"
#include "unit.h"
#include "missile.h"
#include "actions.h"
#include "construct.h"
#include "ai.h"
#include "ccl.h"
#include "cursor.h"
#include "upgrade.h"
#include "depend.h"
#include "font.h"
#include "interface.h"
#include "ui.h"
#include "menus.h"
#include "sound_server.h"
#include "sound.h"
#include "network.h"
#include "settings.h"

/*----------------------------------------------------------------------------
--	Variables
----------------------------------------------------------------------------*/

#ifdef DEBUG
extern SCM CclUnits(void);
#endif

global char* TitleScreen;		/// Titlescreen to show at startup
global char* FreeCraftLibPath;		/// Path for data

    /// Name, Version, Copyright
global char NameLine[] =
    "FreeCraft V" VERSION ", (c) 1998-2000 by The FreeCraft Project.";

    /// Filename of the map to load
local char* MapName = NULL;


/*----------------------------------------------------------------------------
--	Speedups
----------------------------------------------------------------------------*/

global int SpeedMine=SPEED_MINE;	/// speed factor for mine gold
global int SpeedGold=SPEED_GOLD;	/// speed factor for getting gold
global int SpeedChop=SPEED_CHOP;	/// speed factor for chop
global int SpeedWood=SPEED_WOOD;	/// speed factor for getting wood
global int SpeedHaul=SPEED_HAUL;	/// speed factor for haul oil
global int SpeedOil=SPEED_OIL;		/// speed factor for getting oil
global int SpeedBuild=SPEED_BUILD;	/// speed factor for building
global int SpeedTrain=SPEED_TRAIN;	/// speed factor for training
global int SpeedUpgrade=SPEED_UPGRADE;	/// speed factor for upgrading
global int SpeedResearch=SPEED_RESEARCH;/// speed factor for researching

/*--------------------------------------------------------------
	Scroll Speeds
--------------------------------------------------------------*/

global int SpeedKeyScroll=KEY_SCROLL_SPEED;
global int SpeedMouseScroll=MOUSE_SCROLL_SPEED;

/*============================================================================
==	DISPLAY
============================================================================*/

// FIXME: move to video header file
global int VideoWidth;			/// window width in pixels
global int VideoHeight;			/// window height in pixels

global int FrameCounter;		/// current frame number
global int SlowFrameCounter;		/// profile, frames out of sync

// FIXME: not the correct place
global enum MustRedraw_e MustRedraw=RedrawEverything;	/// redraw flags

/*----------------------------------------------------------------------------
--	SAVE/LOAD
----------------------------------------------------------------------------*/

/**
**	Test function for the later save functions.
*/
global void SaveAll(void)
{
    FILE* file;
    time_t now;
    const char* name;

    name="save_file_of_freecraft.ccl";
    // FIXME: must choose better name.
    file=fopen(name,"wb");
    if( !file ) {
	fprintf(stderr,"Can't save to `%s'\n",name);
	return;
    }
    fprintf(file,";;; -----------------------------------------\n");
    fprintf(file,";;; Save file generated by FreeCraft Version " VERSION "\n");
    time(&now);
    fprintf(file,";;;\tDate: %s",ctime(&now));
    fprintf(file,";;;\tMap: %s\n",TheMap.Description);
    fprintf(file,";;; -----------------------------------------\n\n\n");

    SaveUnitTypes(file);
    SaveUnits(file);
    SaveTileset(file);
    SaveMap(file);
    SaveUpgrades(file);
    SaveDependencies(file);

    // FIXME: find all state information which must be saved.

    fclose(file);
}

global void LoadAll(void)
{

}

/*----------------------------------------------------------------------------
--	Random
----------------------------------------------------------------------------*/

/**
**	Syncron rand.
*/
global int SyncRand(void)
{
    static unsigned rnd = 0x87654321;
    int val;

    val=rnd>>16;

    rnd=rnd*(0x12345678 * 4 + 1) + 1;

    return val;
}

/*----------------------------------------------------------------------------
--	Utility
----------------------------------------------------------------------------*/

/**
**	String duplicate/concatenate (two arguments)
*/
global char *strdcat(const char *l, const char *r) {
    char *res = malloc(strlen(l) + strlen(r) + 1);
    if (res) {
        strcpy(res, l);
        strcat(res, r);
    }
    return res;
}

/**
**	String duplicate/concatenate (three arguments)
*/
global char* strdcat3(const char* l, const char* m, const char* r) {
    char* res = malloc(strlen(l) + strlen(m) + strlen(r) + 1);
    if (res) {
        strcpy(res, l);
	strcat(res, m);
        strcat(res, r);
    }
    return res;
}

/*============================================================================
==	MAIN
============================================================================*/

/**
**	Main1, called from guile main / main.
**
**	@param	argc	Number of arguments.
**	@param	argv	Vector of arguments.
*/
global int main1(int argc __attribute__ ((unused)),
	char** argv __attribute__ ((unused)))
{
    printf("%s\n  written by Lutz Sammer, Fabrice Rossi, Vladi Shabanski, Patrice Fortier,\n  Jon Gabrielson, Andreas Arens and others."
#ifdef USE_CCL2
    "\n  SIOD Copyright by George J. Carrette."
#endif
    "\nCompile options "
#ifdef USE_CCL
    "CCL "
#endif
#ifdef USE_CCL2
    "CCL2 "
#endif
#ifdef GUILE_GTK
    "GTK "
#endif
#ifdef USE_THREAD
    "THREAD "
#endif
#ifdef DEBUG
    "DEBUG "
#endif
#ifdef USE_ZLIB
    "ZLIB "
#endif
#ifdef USE_BZ2LIB
    "BZ2LIB "
#endif
#ifdef USE_GLIB
    "GLIB "
#endif
#ifdef USE_SDLA
    "SDL-AUDIO "
#endif
#ifdef USE_SDL
    "SDL "
#endif
#ifdef USE_X11
    "X11 "
#endif
#ifdef WITH_SOUND
    "SOUND "
#endif
    "\n\nFreeCraft may be copied only under the terms of the Artistic License\
\nwhich may be found in the FreeCraft source kit."
    "\n\nDISCLAIMER:\n\
This software is provided as-is.  The author(s) can not be held liable for any\
\ndamage that might arise from the use of this software.\n\
Use it at your own risk.\n"
	,NameLine);

    InitVideo();			// setup video display
#ifdef WITH_SOUND
    if( InitSound() ) {			// setup sound card
	SoundOff=1;
	SoundFildes=-1;
    }
#endif

    //
    //	Show title screen.
    //
    SetClipping(0,0,VideoWidth,VideoHeight);
    if( TitleScreen ) {
	DisplayPicture(TitleScreen);
    }
    Invalidate();

    //
    //  Units Memory Management
    //
    InitUnitsMemory();
    UpdateStats();
    InitUnitTypes();

    // 
    //  Inital menues require some gfx..
    //
    LoadRGB(GlobalPalette, strdcat(FreeCraftLibPath, "/summer.rgb"));
    VideoCreatePalette(GlobalPalette);
    LoadFonts();

    // All pre-start menues are orcish - may need to be switched later..
    SetDefaultTextColors(FontYellow,FontWhite);
    InitMenus(1);
    LoadImages(1);
    LoadCursors(1);
    InitSettings();

    //
    //	Create the game.
    //
    CreateGame(MapName,&TheMap);

    SetStatusLine(NameLine);
    SetMessage("Do it! Do it now!");

    GameMainLoop();

    return 0;
}

/**
**	Exit clone.
**
**	Called from 'Q'.
*/
global volatile void Exit(int err)
{
    IfDebug(
	extern unsigned PfCounterFail;
	extern unsigned PfCounterOk;
	extern unsigned PfCounterDepth;
	extern unsigned PfCounterNotReachable;
    );

    QuitSound();
    NetworkQuit();
    DebugLevel0("Frames %d, Slow frames %d = %d%%\n"
	,FrameCounter,SlowFrameCounter
	,(SlowFrameCounter*100)/(FrameCounter ? : 1));
    IfDebug(
	UnitCacheStatistic();
	DebugLevel0("Path: Error: %u(%u) OK: %u Depth: %u\n"
		,PfCounterFail,PfCounterNotReachable
		,PfCounterOk,PfCounterDepth);
	CclUnits();
    );
    fprintf(stderr,"Thanks for playing FreeCraft.\n");
    exit(err);
}

/**
**	Display the usage.
*/
local void Usage(void)
{
    printf("%s\n  written by Lutz Sammer, Fabrice Rossi, Vladi Shabanski, Patrice Fortier,\n  Jon Gabrielson, Andreas Arens and others."
#ifdef USE_CCL2
    "\n  SIOD Copyright by George J. Carrette."
#endif
"\n\nUsage: freecraft [OPTIONS] [map.pud|map.pud.gz|map.cm|map.cm.gz]\n\
\t-d datapath\tpath to freecraft data\n\
\t-c file.ccl\tccl start file\n\
\t-f factor\tComputer units cost factor\n\
\t-h\t\tHelp shows this page\n\
\t-l\t\tEnable command log to \"command.log\"\n\
\t-p players\tNumber of players\n\
\t-n [localport:]host[:port]\tNetwork argument (port default 6660)\n\
\t-L lag\t\tNetwork lag in # frames\n\
\t-U update\tNetwork update frequence in # frames\n\
\t-s sleep\tNumber of frames for the AI to sleep before it starts\n\
\t-t factor\tComputer units built time factor\n\
\t-v mode\t\tVideo mode (0=default,1=640x480,2=800x600,\n\
\t\t\t\t3=1024x768,4=1600x1200)\n\
\t-D\t\tVideo mode depth = pixel per point (for Win32/TNT)\n\
\t-F\t\tFull screen video mode (only supported with SDL)\n\
\t-S\t\tSync speed (100 = 30 frames/s)\n\
\t-W\t\tWindowed video mode (only supported with SDL)\n\
map is relative to FreeCraftLibPath=datapath, use ./map for relative to cwd\n\
",NameLine);
}

/**
**	The main program: initialise, parse options and arguments.
**
**	@param	argc	Number of arguments.
**	@param	argv	Vector of arguments.
*/
#ifdef __MINGW32__
global int mymain(int argc,char** argv)
#else
global int main(int argc,char** argv)
#endif
{
#ifdef USE_BEOS
    beos_init( argc, argv );
    VideoDepth=32;
#endif
    //
    //	Setup some defaults.
    //
    FreeCraftLibPath=FREECRAFT_LIB_PATH;
#ifdef NEW_NAMES
    TitleScreen=strdup("graphics/ui/title.png");
#else
    TitleScreen=strdup("graphic/title.png");
#endif
#if defined(USE_CCL) || defined(USE_CCL2)
    CclStartFile="ccl/freecraft.ccl";
#endif

    // FIXME: Parse options before or after ccl?

    //
    //	Parse commandline
    //
    for( ;; ) {
	switch( getopt(argc,argv,"c:d:f:hln:p:s:t:v:D:FL:S:U:W?") ) {
#if defined(USE_CCL) || defined(USE_CCL2)
	    case 'c':
		CclStartFile=optarg;
		continue;
#endif
            case 'd':
                FreeCraftLibPath=optarg;
                continue;
	    case 'f':
		AiCostFactor=atoi(optarg);
		continue;
	    case 'l':
		CommandLogEnabled=1;
		continue;
	    case 'p':
		NetPlayers=atoi(optarg);
		continue;
	    case 'n':
		NetworkArg=strdup(optarg);
		continue;
	    case 's':
		AiSleep=atoi(optarg);
		continue;
	    case 't':
		AiTimeFactor=atoi(optarg);
		continue;
	    case 'v':
		switch( atoi(optarg) ) {
		    case 0:
			continue;
		    case 1:
			VideoWidth=640;
			VideoHeight=480;
			continue;
		    case 2:
			VideoWidth=800;
			VideoHeight=600;
			continue;
		    case 3:
			VideoWidth=1024;
			VideoHeight=768;
			continue;
		    case 4:
			VideoWidth=1600;
			VideoHeight=1200;
			continue;
		    default:
			Usage();
			exit(-1);
		}
		continue;

	    case 'L':
		NetworkLag=atoi(optarg);
		continue;
	    case 'U':
		NetworkUpdates=atoi(optarg);
		continue;

	    case 'F':
		VideoFullScreen=1;
		continue;
	    case 'W':
		VideoFullScreen=0;
		continue;
	    case 'D':
		VideoDepth=atoi(optarg);
		continue;
	    case 'S':
		VideoSyncSpeed=atoi(optarg);
		continue;

	    case -1:
		break;
	    case '?':
	    case 'h':
	    default:
		Usage();
		exit(-1);
	}
	break;
    }

    if( argc-optind>1 ) {
	fprintf(stderr,"too many files\n");
	Usage();
	exit(-1);
    }

    if( argc-optind ) {
	MapName=argv[optind];
	--argc;
    }

#if defined(USE_CCL) || defined(USE_CCL2)
    if (CclStartFile[0] != '/' && CclStartFile[0] != '.') {
        CclStartFile = strdcat3(FreeCraftLibPath, "/", CclStartFile);
    }

    CclInit();				// load configurations!
#endif

    main1(argc,argv);			// CclInit may not return!

    return 0;
}

//@}
