/*
 *  acm : an aerial combat simulator for X
 *  Air and wind properties module.
 *  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 <math.h>
#include "pm.h"
#include "../util/prng.h"
#include "../util/units.h"

#define air_IMPORT
#include "air.h"


void air_update(air_Properties * air, double h)
{
	if (h < 36089.2) {
		air->t = units_T0 - 3.56616e-3 * h;
		air->p = units_P0 * pow(air->t / units_T0, 5.255912);  /* lbf/ft^2 */
	}
	else {
		air->t = 389.97;
		air->p = 472.6773 * exp(-units_earth_g * (h - 36089.2) / (units_RA * air->t));  /* lbf/ft^2 */
	}

	air->rho = air->p / (units_RA * air->t);  /* slug/ft^3 */
	air->mach1 = sqrt(units_GM * units_RA * air->t);
}


/*
	Wind has two components: a constant component const_wind[], and a gust
	component gust[] that varies in intensity and frequence. The resulting
	wind is
	
		wind[] = const_wind[] + gust[].
*/


static VPoint wind = {
	0.0 /* from N */,
	0.0 /* from E */,
	0.0 /* from zenith */
};
/* wind speed (ft/s) */


static VPoint const_wind = {
	0.0 /* from N */,
	0.0 /* from E */,
	0.0 /* from zenith */
};
/* Constant wind speed (ft/s) */


static double gust_max = 0.0;
/* Max gust speed (ft/s). */

static VPoint gust = {
	0.0 /* from N */,
	0.0 /* from E */,
	0.0 /* from zenith */
};
/* Current gust speed [ft/s] */


static VPoint target_gust = {
	0.0 /* from N */,
	0.0 /* from E */,
	0.0 /* from zenith */
};
/* Target gust speed (ft/s) */


void
air_set_wind(
	double wd, /* wind direction (deg) */
	double wv) /* wind velocity (kt) */
{
	wd = units_DEGtoRAD(wd);
	wv = units_KTtoFPS(wv);
	const_wind.x = wv * cos(wd);
	const_wind.y = wv * sin(wd);
	const_wind.z = 0.0;
}


void air_set_gust(double _gust_max)
{
	gust_max = _gust_max;
}


#define T1_2 0.5


static void
air_update_gust()
{
	static double t_prev = 0.0, t_next = 0.0;

	double dt, x;

	/*
		Update gust speed:
	*/

	dt = curTime - t_prev;
	t_prev = curTime;
	gust.x += dt / T1_2 * (target_gust.x - gust.x);
	gust.y += dt / T1_2 * (target_gust.x - gust.y);
	gust.z += dt / T1_2 * (target_gust.x - gust.z);

	/*
		Update target gust speed:
	*/

	if( curTime <= t_next )
		return;
	
	x = 2.0 * prng_getDouble() - 1.0;  /* -1.0 <= x <= +1.0 */
	target_gust.x = gust_max * x * x * x * x * x;

	x = 2.0 * prng_getDouble() - 1.0;  /* -1.0 <= x <= +1.0 */
	target_gust.y = gust_max * x * x * x * x * x;

	x = 2.0 * prng_getDouble() - 1.0;  /* -1.0 <= x <= +1.0 */
	target_gust.z = gust_max * x * x * x * x * x;

	/*
		Evaluate time of the next gust evaluation.

		The idea behind this calculation is that the bigger is the
		gust, the more is the frequency of the recalculation. So we
		start with this (approximated) gust module calculation:
	*/

	double m = fabs(target_gust.x) + fabs(target_gust.y) + fabs(target_gust.z);

	t_next = curTime + 10.0 / (m + 5.0);
	
}


static double t_next_gust_upd = 20.0;


VPoint * air_get_wind(double h)
{
	/*
		Update current gust speed:
	*/
	
	if( curTime > t_next_gust_upd ){
		air_update_gust();
		t_next_gust_upd = curTime + 0.1;
	}

	/*
		Calculate total wind speed. The gust intensity decreases as the
		altitude increases.
	*/

	double k = 3000.0 / (h + 3000.0);

	wind.x = const_wind.x + k * gust.x;
	wind.y = const_wind.y + k * gust.y;
	wind.z = const_wind.z + k * gust.z;

	return &wind;
}
