/*
 *  acm : an aerial combat simulator for X
 *  Copyright (C) 1991-1998  Riley Rainey
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 dated June, 1991.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program;  if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave., Cambridge, MA 02139, USA.
 */

#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include "../V/Vlib.h"
#include "../util/error.h"
#include "../util/memory.h"
#include "../wmm/wmm.h"
#include "alarm.h"
#include "astro.h"
#include "dis_if.h"
#include "inventory.h"
#include "planes.h"
#include "pm.h"
#include "vpath_gallery.h"
#include "weapon.h"

#define init_IMPORT
#include "init.h"


#ifdef WINNT
#define SEPARATOR ";"
#else
#define SEPARATOR ":"
#endif

#define DEFAULT_OBJECT_DIRS \
	"." \
	SEPARATOR "objects" \
	SEPARATOR "../objects" \
	SEPARATOR "../../objects"

static char ** objects_dirs = NULL;


static void
init_fileNotFoundError(char * path)
{
	fprintf(stderr, "acm: file `%s' not found. Attempts made:\n", path);
	fprintf(stderr, "    %s\n", path);
	char **p = objects_dirs;
	while ( *p != NULL ) {
		fprintf(stderr, "    %s/%s\n", *p, path);
		p++;
	}
	fprintf(stderr, "Relative paths are resolved against the current working directory:\n");
	char cwd[999];
	fprintf(stderr, "    %s\n", getcwd(cwd, sizeof(cwd)));
	fprintf(stderr, "Hint: use the option -objects path1" SEPARATOR "path2" SEPARATOR "...\n");
}


FILE * init_fopen(char *path, char *access)
{
	return fopen(init_findFile(path), access);
}


char * init_findFile(char *path)
{
	static char resolved[999];
	struct stat statbuf;

	memory_strcpy(resolved, sizeof(resolved), path);
	if (stat(resolved, &statbuf) == 0)
		return resolved;

	char **p = objects_dirs;
	while ( *p != NULL ) {
		snprintf(resolved, sizeof(resolved), "%s/%s", *p, path);
		if (stat(resolved, &statbuf) == 0)
			return resolved;
		p++;
	}

	init_fileNotFoundError(path);
	exit(1);
}


void init_init(char *objects, char *departure_date)
{
	if( objects == NULL )
		objects = DEFAULT_OBJECT_DIRS;
	objects = memory_strdup(objects);
	int size = 0;
	int i = 0;
	objects_dirs = NULL;
	char *s = strtok(objects, SEPARATOR);
	do {
		if ( i >= size ) {
			size = 2 * size + 10;
			objects_dirs = memory_realloc(objects_dirs, size * sizeof( char * ));
		}
		if ( s == NULL ){
			/* REMEMBER: last elements of objects_dirs[] must be NULL: */
			objects_dirs[i++] = NULL;
			break;
		} else {
			objects_dirs[i++] = memory_strdup(s);
		}
		s = strtok(NULL, SEPARATOR);
	} while ( 1 );
	memory_dispose(objects);
	
	zulu_Date departure;
	if( departure_date == NULL || *departure_date == 0 ){
		departure_timestamp = time(NULL);
		zulu_timestampToDate(departure_timestamp, &departure);
	} else {
		if( ! zulu_dateParse(departure_date, &departure) )
			error_external("invalid departure date and time '%s'.\n"
				"Check format and range of each field, examples:\n\n"
				"   2017-10             (2017-10-01T00:00:00 assumed)\n"
				"   2017-10-20          (00:00:00 assumed time)\n"
				"   2017-10-20T12:34    (00 seconds assumed)\n"
				"   2017-10-20T12:34:56\n\n"
				"Allowed year range is [1583,9999].",
				departure_date);
		departure_timestamp = zulu_dateToTimestamp(&departure);
	}
	
	wmm_init( init_findFile("WMM.COF") );
	wmm_setCurrentTime( zulu_dateToYear(&departure) );
	
	astro_init(0, &departure);

    craft *p;
    for ((i = 0, p = ptbl); i < manifest_MAXPLAYERS; (++i, ++p)) {
		p->pIndex = i;
		p->type = CT_FREE;
    }

    for ((i = 0, p = mtbl); i < manifest_MAXPROJECTILES; (++i, ++p)) {
		p->pIndex = i;
		p->type = CT_FREE;
    }

	HUDColor     = gui_getColorIndexString(NULL, "#00ee00");
	whiteColor   = gui_getColorIndexString(NULL, "white");
	blackColor   = gui_getColorIndexString(NULL, "black");
	yellowColor  = gui_getColorIndexString(NULL, "#ee0");
	redColor     = gui_getColorIndexString(NULL, "#f44");
	magentaColor = gui_getColorIndexString(NULL, "orange");
	radarColor   = gui_getColorIndexString(NULL, "#0c0");
	panelBackgroundColor = gui_getColorIndexString(NULL, "#111");
	
	
	inventory_init();
	weapon_init();
	zones = zones_new( init_findFile("zones.txt") );

    /*
     *  Add the periodic resupply check procedure
	 *  FIXME: fuel and weapons resupply currently disabled
     */
    /* id = */ alarm_add(manifest_RESUPPLY_INTERVAL, planes_doResupply, NULL, NULL);
}


void init_term(void)
{
	int i;

	for( i = 0; i < manifest_MAXPLAYERS; i++ ){
		if( ptbl[i].type != CT_FREE ){
			ptbl[i].kill(&ptbl[i], "program terminated");
		}
	}

	for( i = 0; i < manifest_MAXPROJECTILES; i++ ){
		if( mtbl[i].type != CT_FREE ){
			mtbl[i].kill(&mtbl[i], "simulation ended");
		}
	}

	dis_if_close();
	vpath_gallery_free_all();

	for( i=0; ; i++){
		if( objects_dirs[i] != NULL )
			memory_dispose(objects_dirs[i]);
		else
			break;
	}
	memory_dispose(objects_dirs);
	objects_dirs = NULL;
	
	memory_dispose(zones);
	zones = NULL;
}
