#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "weather.h"
#include "game_time.h"

int	area = DEFAULT_AREA;
int 	pseudoseed;
int	temp;
int	prec, prec_type;

static int pseudorand(void);
static int pseudorandom(int);

/* We'll add more areas when we find more tables.
 *
 * Nighttime should actually subtract 3d10 from temperature,
 * at least in mordor, perhaps in other wasteland/desertlike
 * areas too.
 */
struct Area_Weather aw[] = {
{	"Forodwaith (Northern Waste)",
	{{ -25,50,  5 }, { -25,45,  2 }, { -10,35,  5 },
	 {  0, 30, 30 }, {  5, 35,  5 }, { 10, 35, 30 },
	 { 10, 40, 40 }, { 10, 50, 30 }, {  5, 40,  5 },
	 {  0, 35, 30 }, { -5, 30,  5 }, { -10,25,  2 }},
},
{	"Nan Angmar",
	{{ -20,  35,  40 }, { -20,  35,  40 }, { -20,  35,  40 },
	{   0,  35,  40 }, {  35,  10,  15 }, {  40,  20,  15 },
	{  50,  15,  25 }, {  55,  10,  25 }, {  50,  27,  25 },
	{  35,  15,  40 }, {  20,  15,  40 }, {  15,   5,  40 }},
},
{	"Gundalok",
	{{ 10, 22, 15 }, { 15, 17, 15 }, {  35,  10,  40 },
	{  40, 20, 25 }, { 40, 20, 25 }, {  70,  10,  25 },
	{  70, 10, 25 }, { 75, 10, 25 }, {  70,  10,  25 },
	{  60, 10, 25 }, { 45, 15, 25 }, {  20,  20,  40 }},
},
{	"Northern Misty Mts: Foothills",
	{{ 15, 15, 40 }, {  15, 15, 60 }, {  15, 15, 60 },
	{  20, 15, 40 }, {  25, 15, 40 }, {  25, 20, 25 },
	{  30, 20, 25 }, {  40, 20, 25 }, {  45, 20, 15 },
	{  40, 20, 25 }, {  35, 15, 40 }, {  25, 15, 40 }},
},
{	"Rhudaur",
	{{   5,  20,  40 }, {   5,  20,  40 }, {  15,  20,  40 },
	{  30,  20,  25 }, {  50,  15,  25 }, {  65,  10,  15 },
	{  65,  10,  25 }, {  65,  10,  25 }, {  60,  10,  25 },
	{  45,  15,  40 }, {  30,  15,  25 }, {  15,  15,  40 }},
},
{	"Arthedain: The North Downs",
	{{ 20, 20, 45 }, { 10, 15, 40 }, { 15, 20, 30 },
	 { 25, 20, 40 }, { 35, 20, 40 }, { 40, 20, 40 },
	 { 50, 20, 40 }, { 50, 25, 50 }, { 50, 25, 50 },
	 { 50, 20, 45 }, { 40, 20, 50 }, { 30, 20, 45 }},
},
{	"Southern Anduin Valley",
	{{ 25,  20,  15 }, {  30,  20,  15 }, {  30,  20,  25 },
	{  45,  20,  25 }, {  55,  20,  25 }, {  60,  20,  15 },
	{  65,  20,  15 }, {  65,  20,  15 }, {  55,  20,  25 },
	{  45,  20,  40 }, {  35,  20,  25 }, {  30,  20,  15 }},
},
{	"Arthedain",
	{{ 10,  22,  15 }, {  10,  22,  15 }, {  28,  12,  40 },
	{  38,  17,  25 }, {  60,  10,  25 }, {  70,  10,  15 },
	{  70,  10,  25 }, {  70,  10,  25 }, {  67,  10,  25 },
	{  50,  17,  25 }, {  30,  20,  25 }, {  12,  23,  40 }},
},
{	"Arthedain: Hills of Evendim",
	{{ 15, 15, 35 }, { 10, 15, 30 }, { 15, 15, 40 },
	 { 20, 15, 30 }, { 30, 15, 25 }, { 35, 15, 30 },
	 { 45, 15, 35 }, { 60, 15, 35 }, { 60, 15, 40 },
	 { 40, 35, 35 }, { 35, 25, 35 }, { 25, 20, 45 }},
},
{	"The Shire",
	{{ 25, 15, 45 }, { 15, 20, 55 }, { 20, 15, 45 },
	 { 30, 20, 45 }, { 35, 25, 45 }, { 50, 15, 50 },
	 { 60, 15, 45 }, { 65, 15, 50 }, { 65, 15, 55 },
	 { 55, 20, 50 }, { 45, 20, 55 }, { 35, 20, 45 }},
},
{	"Mirkwood",
	{{ 10, 35, 30 }, { 10, 30,  5 }, { 20, 30, 30 },
	 { 30, 30, 40 }, { 40, 25, 30 }, { 50, 20, 40 },
	 { 50, 15, 60 }, { 55, 30, 60 }, { 55, 25, 30 },
	 { 45, 20, 40 }, { 35, 25, 30 }, { 20, 25, 30 }},
},
{	"Rhovanion: Lowlands",
	{{ 10, 20, 30 }, {  5, 30,  5 }, { 15, 30,  5 },
	 { 25, 30, 30 }, { 30, 30, 30 }, { 45, 20, 40 },
	 { 50, 30, 60 }, { 55, 35, 40 }, { 55, 30, 30 },
	 { 30, 35, 30 }, { 25, 35, 30 }, { 15, 30, 30 }},
},
{	"Rhovanion: Highlands",
	{{ -10,40, 30 }, { -15,40, 30 }, { -5, 35, 40 },
	 {  5, 35, 40 }, { 15, 35, 30 }, { 25, 35, 40 },
	 { 25, 40, 40 }, { 25, 50, 40 }, { 20, 45, 30 },
	 { 15, 40, 30 }, { 10, 40,  5 }, {  0, 40,  5 }},
},
{	"Wold & the Downs",
	{{ 20, 25, 25 }, { 15, 25, 25 }, { 25, 20, 25 },
	 { 30, 20, 25 }, { 35, 20, 25 }, { 40, 20, 20 },
	 { 50, 20, 15 }, { 60, 20, 15 }, { 65, 20, 20 },
	 { 60, 15, 25 }, { 50, 15, 25 }, { 40, 15, 25 }},
},
{	"Cardolan: Highlands",
	{{ 20, 15, 25 }, { 20, 20, 15 }, { 25, 20, 25 },
	 { 35, 20, 25 }, { 35, 25, 25 }, { 45, 25, 25 },
	 { 50, 30,  5 }, { 65, 25, 15 }, { 55, 25, 25 },
	 { 40, 30, 40 }, { 30, 25, 15 }, { 20, 20, 25 }},
},
{	"Cardolan: Mintyrnath",
	{{ 20, 15, 15 }, { 25, 15, 15 }, { 25, 20, 40 },
	 { 40, 15, 25 }, { 40, 20, 25 }, { 50, 20, 15 },
	 { 55, 30,  5 }, { 70, 20, 15 }, { 55, 30, 25 },
	 { 40, 35, 40 }, { 30, 30, 15 }, { 20, 25, 15 }},
},
{	"Cardolan: Minhiriath",
	{{ 25, 15, 15 }, { 25, 20, 25 }, { 30, 20, 40 },
	 { 45, 15, 25 }, { 45, 20, 25 }, { 50, 25, 15 },
	 { 55, 25, 15 }, { 65, 20, 15 }, { 55, 25, 25 },
	 { 45, 25, 40 }, { 35, 25, 15 }, { 25, 20, 15 }},
},
{	"Fangorn Forest",
	{{ 35,  20,  25 }, {  30,  20,  25 }, {  35,  20,  25 },
	{  40,  20,  25 }, {  45,  15,  40 }, {  50,  10,  40 },
	{  60,  10,  25 }, {  65,  10,  25 }, {  70,  10,  15 },
	{  60,  15,  25 }, {  55,  10,  25 }, {  40,  20,  25 }},
},
{	"Southern Misty Mts: Foothills",
	{{ 20, 20, 20 }, { 15, 20, 20 }, { 20, 20, 20 },
	 { 25, 20, 40 }, { 35, 15, 40 }, { 40, 20, 20 },
	 { 50, 20, 20 }, { 55, 20,  5 }, { 60, 15,  5 },
	 { 50, 20, 20 }, { 50, 15, 20 }, { 45, 15, 20 }},
},
{	"Dunland: Gwaitho Plain",
	{{ 30, 20, 25 }, { 25, 20, 25 }, { 30, 20, 25 },
	 { 35, 20, 25 }, { 40, 15, 40 }, { 45, 15, 25 },
	 { 55, 20, 25 }, { 60, 20,  5 }, { 65, 15,  5 },
	 { 60, 15, 25 }, { 50, 15, 25 }, { 40, 15, 25 }},
},
{	"Dunland: Dunnish Highlands",
	{{ 25, 20, 25 }, { 20, 20, 40 }, { 25, 15, 40 },
	 { 30, 15, 25 }, { 40, 10, 40 }, { 45, 15, 25 },
	 { 55, 15, 25 }, { 60, 15, 25 }, { 65, 10,  5 },
	 { 55, 15, 25 }, { 45, 20, 40 }, { 35, 20, 40 }},
},
{	"Ost-in-Edhil",
	{{ 30, 15, 20 }, { 25, 20, 20 }, { 30, 20, 20 },
	 { 35, 20, 20 }, { 40, 15, 40 }, { 45, 15, 20 },
	 { 55, 20,  5 }, { 60, 20,  5 }, { 65, 15,  3 },
	 { 60, 15,  5 }, { 55, 15,  5 }, { 50, 15,  5 }},
},
{	"Redhorn Pass",
	{{ 10, 15, 60 }, { 15, 15, 60 }, { 15, 15, 40 },
	 { 20, 15, 40 }, { 25, 15, 40 }, { 25, 20, 20 },
	 { 30, 20, 20 }, { 40, 20, 20 }, { 45, 20,  5 },
	 { 40, 20, 20 }, { 35, 15, 20 }, { 20, 15, 40 }}
},
{	"Rohan (Northern)",
	{{ 25, 20, 25 }, { 20, 20, 25 }, { 25, 20, 25 },
	 { 30, 20, 25 }, { 35, 15, 40 }, { 40, 15, 40 },
	 { 50, 15, 25 }, { 55, 15, 25 }, { 60, 15, 15 },
	 { 55, 15, 15 }, { 50, 10, 25 }, { 40, 15, 25 }},
},
{	"Rohan (Southern)",
	{{ 30, 20, 25 }, { 25, 20, 25 }, { 30, 20, 25 },
	 { 35, 20, 25 }, { 40, 15, 40 }, { 45, 15, 40 },
	 { 55, 15, 25 }, { 60, 15, 25 }, { 65, 10, 25 },
	 { 60, 10, 40 }, { 50, 10, 25 }, { 40, 15, 25 }},
},
{	"Northern Ithilien",
	{{ 20,  15,  40 }, {  10,  30,  45 }, {  15,  30,  40 },
	{  25,  30,  40 }, {  35,  30,  35 }, {  50,  20,  30 },
	{  60,  20,  25 }, {  65,  25,  20 }, {  60,  20,  10 },
	{  50,  25,  25 }, {  40,  20,  30 }, {  30,  20,  25 }},
},
{	"Mordor: Udûn",
	{{ 35,  15,  10 }, {  40,  15,  15 }, {  40,  15,  15 },
	{  40,  20,  18 }, {  45,  20,  15 }, {  50,  30,  12 },
	{  70,  15,   5 }, {  70,  20,   4 }, {  70,  40,   3 },
	{  50,  30,   5 }, {  40,  25,   8 }, {  30,  25,  13 }},
},
{	"Mordor: Devastation/The Grip",
	{{ 30,  15,   6 }, {  35,  15,   6 }, {  35,  15,   8 },
	{  35,  25,  10 }, {  40,  20,   8 }, {  45,  30,   7 },
	{  65,  20,   3 }, {  75,  20,   2 }, {  80,  35,   2 },
	{  65,  15,   5 }, {  45,  15,   6 }, {  35,  20,  10 }},
},
{	"Mordor: Gwathiraug",
	{{ 30,  10,  10 }, {  35,  15,  20 }, {  40,  15,  20 },
	{  40,  25,  25 }, {  40,  20,  15 }, {  45,  30,  10 },
	{  50,  30,   5 }, {  65,  25,   5 }, {  70,  40,   5 },
	{  45,  30,   8 }, {  35,  25,  10 }, {  25,  20,  15 }},
},
{	"Mordor: Gaer-Durlith",
	{{ 40,  15,   2 }, {  45,  15,   3 }, {  45,  15,   3 },
	{  50,  15,   4 }, {  50,  20,   3 }, {  55,  30,   3 },
	{  75,  15,   1 }, {  80,  25,   1 }, {  90,  30,   1 },
	{  75,  20,   2 }, {  50,  15,   3 }, {  25,  25,   3 }},
},
{	"Mordor: Morgul Vale",
	{{ 30,  15,  35 }, {  30,  20,  40 }, {  35,  20,  35 },
	{  45,  15,  35 }, {  55,  15,  30 }, {  60,  15,  25 },
	{  60,  20,  20 }, {  60,  25,  20 }, {  60,  20,  15 },
	{  55,  15,  25 }, {  45,  15,  30 }, {  35,  15,  30 }},
},
{	"South Gondor: Mountains",
	{{ 20, 20, 15 }, { 25, 20, 15 }, { 25, 20, 25 },
	 { 40, 20, 25 }, { 50, 20, 25 }, { 55, 20, 15 },
	 { 60, 20, 15 }, { 60, 20, 15 }, { 50, 20, 25 },
	 { 40, 20, 40 }, { 30, 20, 25 }, { 25, 20, 15 }},
},
{	"South Gondor: Inland Vales",
	{{ 25, 20, 15 }, { 30, 20, 15 }, { 30, 20, 25 },
	 { 45, 20, 25 }, { 55, 20, 25 }, { 60, 20, 15 },
	 { 65, 20, 15 }, { 65, 20, 15 }, { 55, 20, 25 },
	 { 45, 20, 40 }, { 35, 20, 25 }, { 30, 20, 15 }},
},
{	"South Gondor: Coastlands",
	{{ 35, 15, 15 }, { 40, 15, 15 }, { 45, 10, 25 },
	 { 55, 15, 25 }, { 60, 15, 25 }, { 65, 15, 15 },
	 { 70, 15, 15 }, { 70, 15, 15 }, { 60, 15, 25 },
	 { 55, 15, 40 }, { 45, 15, 25 }, { 40, 15, 25 }},
}
};

/* Who can understand those idiotic but stupid farenheit degrees? */
int
farenheit_to_celcius(int f)
{
	return ((f - 32) * 10) / 18;
}

int
celcius_to_farenheit(int c)
{
	return ((c * 18) / 10) + 32;
}

static int
pseudorand()
{
	pseudoseed = ((pseudoseed * 997775) ^ 0xaaaaaaaa);
	return pseudoseed;
}

static int
pseudorandom(int n)
{
	return (rand() >> 8) % n;
}

/* Todo: Winds, wind speed, direction, cloud cover, mist, ... */
/* Todo: Special weather (like the storms of Cardolan etc.) */
/* Todo: Lower temperature at nighttime */
void
todays_weather()
{
	int		m;
	unsigned int	saveseed;

	/* We need to save a good random seed for dice throwing... */
	saveseed = rand();

	pseudoseed = 54001 * query_year_day() * query_year() * (area + 1);
	srand(pseudorand());

	m = query_month();

	/* Festival? Into which month it belongs? */
	if (m == -1) m = query_festival_month();

	m--;

#if 0
	fprintf(stderr, "%s (%d), month %d: %d %d %d\n",
		aw[area].area_name,
		area,
		m,
		aw[area].w_types[m].temp_base,
		aw[area].w_types[m].temp_var,
		aw[area].w_types[m].prec_chance);
#endif

	temp = aw[area].w_types[m].temp_base +
		pseudorandom(aw[area].w_types[m].temp_var);

	if (aw[area].w_types[m].prec_chance >= pseudorandom(100)) {
		prec = 1;
		prec_type = (temp < 32);
	}

	else prec = 0;

	/* Get the good seed back - ain't we random today */
	srand(saveseed);
}

static char wdesc[512];

char *
weather_desc()
{
	todays_weather();

	if (prec)
		sprintf(wdesc, "Weather: Temperature %d°F (%d°C), Precipitation (%s)",
			temp,
			farenheit_to_celcius(temp),
			prec_type ? "Snow/Fleet" : "Water");
	else
		sprintf(wdesc, "Weather: temperature %d°F (%d°C)",
			temp,
			farenheit_to_celcius(temp));

	return wdesc;
}
