/*
 *  acm : an aerial combat simulator for X
 *  Copyright (C) 2008  Umberto Salsi
 *
 *  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 <string.h>

#include "../util/error.h"
#include "../util/memory.h"
#include "../util/units.h"
#include "adf.h"
#include "aps.h"
#include "hsi.h"
#include "pm.h"
#include "damage.h"
#include "draw.h"
#include "planes.h"
#include "radar.h"
#include "terrain.h"
#include "vpath.h"
#include "gear.h"

#define panel_IMPORT
#include "panel.h"

#define GEARDOWN (M_PI / 2.0)

#define FLAP_ANGLE_SCALE 2.0
/*
	The angular deflection of the flaps is amplified for readability:

	(actual drawing angle) = FLAP_ANGLE_SCALE * (actual flaps deflection)
*/

#define MAX_BANK_ANGLE_SCALE 9.0
#define MAX_BANK_ANGLE_OFFSET units_DEGtoRAD(-225)
/*
	The max angle of bank scale ranges from 5 to 25 DEG with stepd of 5
	DEG. For readability, the scale is expanded and rotated so that 5 DEG
	appears to the left, and 25 DEG to the right. These are the coefficients
	of the linear transformation:

	(actual drawing angle) = MAX_BANK_ANGLE_OFFSET
		+ MAX_BANK_ANGLE_SCALE * (current max bank angle)
*/


#define LIGHTS_N 14
/* max no. of lights allowed in the lights panel */


static struct {
	long      mask;
	char     *name;
	int       blink;  /* does this lights blink when on? */
} *pptr, panelVec[] = {

	/* Sub-system failure indicators: */
	{ SYS_ENGINE1, "OIL", TRUE },
	{ SYS_HYD1, "HYD1", TRUE },
	{ SYS_HYD2, "HYD2", TRUE },
	{ SYS_GEN1, "GEN1", TRUE },
	{ SYS_GEN2, "GEN2", TRUE },
	{ SYS_FLAPS, "FLAP", TRUE },
	{ SYS_SPEEDBRAKE, "SPBRK", TRUE },
	{ SYS_RADAR, "RADAR", TRUE },
	{ SYS_TEWS, "TEWS", TRUE },
	{ SYS_HUD, "HUD", TRUE },

	/* Status and warning indicators: */
	{ FLAG_MAX_G_LOAD, "G-LOAD", TRUE },
	{ FLAG_LOWFUEL, "FUEL", FALSE },
	{ FLAG_SPEEDBRAKE, "SPD BRK", FALSE },
	{ FLAG_WHEELBRAKE, "BRAKES", FALSE },
	{ 0, (char *) 0 }
};


static vpath_Type *panel_fixed = NULL;
static vpath_Type *panel_flap  = NULL;
static vpath_Type *panel_bank_pointer = NULL;
static vpath_Type *panel_handle_up = NULL;


static vpath_Type * radar_altimeter_scale = NULL;
/*
	The radar-altimeter scale is 1.0 wide. The zero altitude is the line
	between (0,0) and (1,0); the 100 ft mark is a line between (0,1) and
	(1,1); the 200 ft mark is at (0,2)-(1,2) and so on. Above 500 ft the
	step becomes 200 ft. So in general the altitude h (ft) is located at

	y = -h/100              if h <= 500 ft
	y = -5 - (h-500)/200    if h > 500 ft
*/


static void panel_cleanup()
{
	memory_dispose(panel_fixed);
	memory_dispose(panel_flap);
	memory_dispose(panel_bank_pointer);
	memory_dispose(panel_handle_up);
	memory_dispose(radar_altimeter_scale);
}


/**
 * Prepare all the VPath needed for the panel, either fixed drawings
 * (labels, scales, etc.) and the moving parts (flaps, pointers, etc.).
 * This virtual drawings take place in a square box 1.0x1.0 with origin in
 * its top-left corner, so that, once properly scaled and translated to
 * their actual position in screen, they can be drawn.
 */
static void panel_create_vpaths()
{
	vpath_Type *p;
	double x, y, co, si, r, r1, r2, r3, r4, w, h;
	int a;
	VMatrix m;
	char s[10];

	if( panel_fixed != NULL )
		return;
	
	memory_registerCleanup(panel_cleanup);

	/*
		Fixed drawings:
	*/

	p = vpath_new();

	/* Wing profile without flap: */

	VIdentMatrix(&m);
	VScaleMatrix(&m, 0.030, 0.030, 1.0);
	VTranslate(&m, 0.05, 0.05, 0.0);
	vpath_draw_string(p, "FLAPS", 5, &m);
	vpath_moveTo(p, &(VPoint){0.05, 0.15, 0.0});
	vpath_lineTo(p, &(VPoint){0.07, 0.13, 0.0});
	vpath_lineTo(p, &(VPoint){0.13, 0.12, 0.0});
	vpath_lineTo(p, &(VPoint){0.23, 0.13, 0.0});
	vpath_lineTo(p, &(VPoint){0.22, 0.15, 0.0});
	vpath_lineTo(p, &(VPoint){0.23, 0.17, 0.0});
	vpath_lineTo(p, &(VPoint){0.08, 0.17, 0.0});
	vpath_lineTo(p, &(VPoint){0.065, 0.165, 0.0});
	vpath_lineTo(p, &(VPoint){0.05, 0.15, 0.0});

	/* Flaps deflection scale, with angle amplified by 2 for readability: */
	x = 0.25;
	y = 0.15;
	r1 = 0.17;  /* notchs internal radius */
	r2 = 0.19;  /* short notchs external radius */
	r3 = 0.21;  /* long notchs external radius */
	r4 = 0.25;  /* label's center radius */
	for( a = 0; a <= 40; a += 5 ){
		co = cos( FLAP_ANGLE_SCALE * units_DEGtoRAD(a) );
		si = sin( FLAP_ANGLE_SCALE * units_DEGtoRAD(a) );
		if( a % 10 == 0 )
			r = r3;
		else
			r = r2;
		vpath_moveTo(p, &(VPoint){x + r1*co, y + r1*si, 0.0});
		vpath_lineTo(p, &(VPoint){x + r*co, y + r*si, 0.0});

		/* Draw label: */
		if( a % 10 == 0 ){
			sprintf(s, "%d", a);
			w = 0.025; /* font width */
			h = 0.030; /* font height */
			VIdentMatrix(&m);
			VScaleMatrix(&m, w, h, 1.0);
			VTranslate(&m, x + r4*co - 0.5*strlen(s)*w,
				y + r4*si + 0.5*h, 0.0);
			vpath_draw_string(p, s, strlen(s), &m);
		}
	}

	/* Max bank fixed scale: */
	VIdentMatrix(&m);
	VScaleMatrix(&m, 0.03, 0.03, 1.0);
	VTranslate(&m, 0.65, 0.05, 0.0);
	vpath_draw_string(p, "MAX BANK", 8, &m);
	x = 0.80;
	y = 0.30;
	r1 = 0.08;  /* notchs internal radius */
	r3 = 0.11;  /* long notchs external radius */
	r4 = 0.15;  /* label's center radius */
	for( a = 5; a <= 25; a += 5 ){
		co = cos( MAX_BANK_ANGLE_OFFSET + MAX_BANK_ANGLE_SCALE * units_DEGtoRAD(a) );
		si = sin( MAX_BANK_ANGLE_OFFSET + MAX_BANK_ANGLE_SCALE * units_DEGtoRAD(a) );
		vpath_moveTo(p, &(VPoint){x + r1*co, y + r1*si, 0.0});
		vpath_lineTo(p, &(VPoint){x + r3*co, y + r3*si, 0.0});

		/* Draw label: */
		sprintf(s, "%d", a);
		w = 0.025; /* font width */
		h = 0.030; /* font height */
		VIdentMatrix(&m);
		VScaleMatrix(&m, w, h, 1.0);
		VTranslate(&m, x + r4*co - 0.5*strlen(s)*w,
			y + r4*si + 0.5*h, 0.0);
		vpath_draw_string(p, s, strlen(s), &m);
	}

	/* Max bank, knob: */
	r1 = 0.06;
	vpath_moveTo(p, &(VPoint){0.80 + r1, 0.30, 0.0});
	for( a = 30; a <= 360; a += 30 ){
		vpath_lineTo(p, &(VPoint){0.80 + r1*cos(units_DEGtoRAD(a)),
			0.30 + r1*sin(units_DEGtoRAD(a)), 0.0});
	}

	/* Handle attachment: */

	/* Gear lights: */

	panel_fixed = p;

	/*
		Flap with pivot in (0,0,0) indicating 0 DEG deflection:
	*/

	p = vpath_new();
	vpath_moveTo(p, &(VPoint){-0.02,  0.00, 0.0});
	vpath_lineTo(p, &(VPoint){ 0.00, -0.02, 0.0});
	vpath_lineTo(p, &(VPoint){ 0.15,  0.00, 0.0});
	vpath_lineTo(p, &(VPoint){ 0.00,  0.02, 0.0});
	vpath_lineTo(p, &(VPoint){-0.02,  0.00, 0.0});
	panel_flap = p;

	/*
		Max bank knob, oriented right:
	*/

	p = vpath_new();
	vpath_lineTo(p, &(VPoint){0.06,  0.00, 0.0});
	vpath_lineTo(p, &(VPoint){0.025, 0.0, 0.0});
	panel_bank_pointer = p;

	/*
		Handle up, centered on its fulcrum:
	*/

	p = vpath_new();
	vpath_moveTo(p, &(VPoint){-0.05, -0.25, 0.0});
	vpath_lineTo(p, &(VPoint){ 0.05, -0.25, 0.0});
	vpath_lineTo(p, &(VPoint){ 0.05, -0.05, 0.0});
	vpath_lineTo(p, &(VPoint){-0.05, -0.05, 0.0});
	vpath_lineTo(p, &(VPoint){-0.05, -0.25, 0.0});

	vpath_moveTo(p, &(VPoint){-0.02, -0.05, 0.0});
	vpath_lineTo(p, &(VPoint){-0.02,  0.00, 0.0});
	vpath_lineTo(p, &(VPoint){-0.01,  0.01, 0.0});
	vpath_lineTo(p, &(VPoint){ 0.01,  0.01, 0.0});
	vpath_lineTo(p, &(VPoint){ 0.02,  0.00, 0.0});
	vpath_lineTo(p, &(VPoint){ 0.02, -0.05, 0.0});

	vpath_moveTo(p, &(VPoint){-0.03, -0.05, 0.0});
	vpath_lineTo(p, &(VPoint){-0.03,  0.10, 0.0});
	vpath_lineTo(p, &(VPoint){ 0.03,  0.10, 0.0});
	vpath_lineTo(p, &(VPoint){ 0.03, -0.05, 0.0});
	panel_handle_up = p;

	/*
		Handle down:
	*/

	/* We simply draw the handle up with y axis reversed. */

}


static void panel_gear_and_flaps_draw(craft * c, viewer * u)
{
	int       x, y, pos[3];
	Alib_Window  *w;
	double    xscale, yscale, curMaxBank;
	VMatrix   m;
	static _BOOL  blink = FALSE;
	static double blink_toggle_time = 0.0;


	void gear_light(double xpos, double ypos, double gear_pos, char *label)
	{
		int h, v, width, height, len, fh, fw;
		Alib_Rect r;

		h = x + xscale*xpos;
		v = y + yscale*ypos;
		width = 0.25*xscale;
		height = 0.20*yscale;
		Alib_setRect(&r, h, v, h + width, v + height);
		if( (gear_pos == 0.0) || (blink && (gear_pos < GEARDOWN)) )
			Alib_fillRect(u->w, &r, panelBackgroundColor);
		else
			Alib_fillRect(u->w, &r, radarColor);

		Alib_drawRect(u->w, &r, blackColor);
		Alib_expandRect(&r, 1, 1);
		Alib_drawRect(u->w, &r, blackColor);

		len = strlen(label);
		fh = height/6;
		fw = fh;
		VDrawStrokeString(u->v,
			h + width/2 - len*fw/2,
			v + height/2 + fh/2,
			label, len, fh, blackColor);
	}


	if( curTime > blink_toggle_time ){
		blink = ! blink;
		if( blink )
			blink_toggle_time = curTime + 0.5;
		else
			blink_toggle_time = curTime + 0.7;
	}

	if( panel_fixed == NULL )
		panel_create_vpaths();

	w = u->w;
	x = u->gear.a.x;
	y = u->gear.a.y;
	xscale = (double) RectWidth(u->gear);
	yscale = (double) RectHeight(u->gear);

	Alib_setClipRect(w, &u->gear);


	/*
		Update gear lights status:
	*/

	pos[0] = gear_nosePosition(c);
	pos[1] = gear_leftPosition(c);
	pos[2] = gear_rightPosition(c);

	/*
		Fixed drawings
	*/

	VIdentMatrix(&m);
	VScaleMatrix(&m, xscale, yscale, 1.0);
	VTranslate(&m, x, y, -1.0);
	vpath_stroke(panel_fixed, &m, w, whiteColor);

	/*
	 *  Draw flaps current state
	 */
	
	VIdentMatrix(&m);
	VRotate(&m, ZRotation, FLAP_ANGLE_SCALE * c->curFlap);
	VScaleMatrix(&m, xscale, yscale, 1.0);
	VTranslate(&m, x + 0.25*xscale, y + 0.15*yscale, -1.0);
	vpath_stroke(panel_flap, &m, w, whiteColor);

	/*
	 *  Draw flaps commanded setting
	 */
	
	VIdentMatrix(&m);
	VRotate(&m, ZRotation, FLAP_ANGLE_SCALE * c->flapSetting);
	VScaleMatrix(&m, xscale, yscale, 1.0);
	VTranslate(&m, x + 0.25*xscale, y + 0.15*yscale, -1.0);
	vpath_stroke(panel_flap, &m, w, magentaColor);

	/*
		Draw max bank setting
	*/

	curMaxBank = units_DEGtoRAD( aps_bank_max_get(c) );
	VIdentMatrix(&m);
	VRotate(&m, ZRotation, MAX_BANK_ANGLE_OFFSET
		+ MAX_BANK_ANGLE_SCALE*curMaxBank);
	VScaleMatrix(&m, xscale, yscale, 1.0);
	VTranslate(&m, x + 0.8*xscale, y + 0.30*yscale, -1.0);
	vpath_stroke(panel_bank_pointer, &m, w, magentaColor);

	/*
		Draw gear handle
	*/

	if( gear_isHandleDown(c) ){
		VIdentMatrix(&m);
		VScaleMatrix(&m, xscale, /* upside-down */ -yscale, 1.0);
	} else {
		VIdentMatrix(&m);
		VScaleMatrix(&m, xscale, yscale, 1.0);
	}
	VTranslate(&m, x + 0.25*xscale, y + 0.70*yscale, -1.0);
	vpath_stroke(panel_handle_up, &m, w, whiteColor);
		
	/*
		Draw gear lights:
	*/

	if( c->cinfo->rn.x > c->cinfo->rm.x ){
		/* Tricycle: */
		gear_light(0.55, 0.55, pos[0], "Nose");
		gear_light(0.40, 0.80, pos[1], "Left");
		gear_light(0.70, 0.80, pos[2], "Right");
	
	} else {
		/* Bicycle: */
		gear_light(0.55, 0.80, pos[0], "Tail");
		gear_light(0.40, 0.55, pos[1], "Left");
		gear_light(0.70, 0.55, pos[2], "Right");
	}
}


#define MAX_ALTITUDE 2500
#define THR_ALTITUDE 500

#ifdef FIXME_UNUSED_BUT_STILL_USEFUL_REFERENCE
static double normalized_h(double h)
/*
	Map the altitude h >= 0.0 ft to the range [0.0,1.0].
	Altituded above MAX_ALTITUDE ft are mapped into 1.0.
*/
{
	if( h > MAX_ALTITUDE )
		return 1.0;
	if( h < 0.0 )
		return 0.0;
	if( h <= THR_ALTITUDE )
		return h/THR_ALTITUDE*0.5;
	else
		return  0.5 + 0.5*(h - THR_ALTITUDE)/(MAX_ALTITUDE - THR_ALTITUDE);
}
#endif


static double map_altitude_to_y(double h)
/* Maps altitude h (ft) to y of the radar_altimeter_scale */
{
	if( h <= 500.0 )
		return -0.01*h;
	else
		return -5.0 - 0.005*(h - 500.0);
}


#ifdef FIXME_UNUSED_BUT_STILL_USEFUL_REFERENCE
static double map_y_to_altitude(double y)
/* Maps y of the radar_altimeter_scale into the altitude h (ft) */
{
	if( y >= -5.0 )
		return -100.0*y;
	else
		return 500.0 - 200.0*(y - 5.0);
}
#endif


static void build_radar_altimeter_scale()
{
	vpath_Type *p;
	int h_inc, h, s_len;
	double fw, fh, y, s_width;
	char s[10];
	VMatrix m;

	p = vpath_new();

	vpath_moveTo(p, &(VPoint){0.0, 0.0, 0.0});
	vpath_lineTo(p, &(VPoint){1.0, 0.0, 0.0});

	fw = 0.15;
	fh = 1.6*fw;
	h_inc = 100;

	for( h = 100; h <= 2500; h += h_inc ){
		if( h == 500 ) h_inc = 200;

		y = map_altitude_to_y(h);

		sprintf(s, "%d", h);
		s_len = strlen(s);
		s_width = fw*s_len;
		VIdentMatrix(&m);
		VScaleMatrix(&m, fw, fh, 1.0);
		VTranslate(&m, 0.5 - 0.5*s_width, y + fh/2.0, 0.0);
		vpath_draw_string(p, s, s_len, &m);

		vpath_moveTo(p, &(VPoint){0.0, y, 0.0});
		vpath_lineTo(p, &(VPoint){0.5 - 0.5*s_width - 0.1, y, 0.0});

		vpath_moveTo(p, &(VPoint){1.0, y, 0.0});
		vpath_lineTo(p, &(VPoint){0.5 + 0.5*s_width + 0.1, y, 0.0});
	}

	radar_altimeter_scale = p;
}


static void panel_radar_altimeter(viewer *u)
{
	double yscale, y0, h;
	craft *c;
	Alib_Rect clip;
	Alib_Window *w;
	VMatrix m;

	w = u->w;

	/* Clear area: */
	Alib_setClipRect(w, &u->radar_altimeter);

	/* Draw frame: */
	Alib_drawRect(w, &u->radar_altimeter, whiteColor);

	/* Clip to internal frame: */
	clip = u->radar_altimeter;
	Alib_expandRect(&clip, -1, -1);
	Alib_setClipRect(w, &clip);

	/* Get current altitude over the ground: */
	c = u->c;
	h = units_METERStoFEET(c->w.z - terrain_localAltitude(c))
		- c->cinfo->rm.z - c->cinfo->Gm - c->cinfo->cmMax;
	
	/*
		Mapping between screen y and altitude h:

		y = y0 - yscale*map_altitude_to_y(h)  and its reverse:
		h = map_y_to_altitude((y - y0)/yscale)

		The reference mark is located at the center of the scale.
	*/

	y0 = RectMiddleY(clip);
	yscale = 0.25*RectHeight(clip);  /* 2 marks above and below reference */

	if( h > 2900.0 ){

		Alib_drawLine(w, clip.a.x, clip.a.y, clip.b.x, clip.b.y,
			whiteColor);

	} else {
		double y_h;
		Alib_Rect g;

		y_h = y0 - yscale * map_altitude_to_y(h);

		/* Draw sky: */
		/***
		g = clip;
		g.b.y = (int) (y_h + 0.5);
		AlibFillRectangle(w, &g, attitudeSkyColor->cIndex);
		***/

		/* Draw ground: */
		g = clip;
		g.a.y = (int) (y_h + 0.5);
		if( g.a.y < clip.b.y ){
			int i, x, B, H, W;
			H = RectHeight(g);
			W = RectWidth(g);
			B = W/4;
			Alib_fillRect(w, &g, yellowColor);
			for( i = g.a.x + B; i < g.b.x + W + H; i += 2*B ){
				for( x = i; x < i + B; x++ ){
					Alib_drawLine(w, x, g.a.y, x - H, g.a.y + H, blackColor);
				}
			}
		}

		/* Draw scale: */
		VIdentMatrix(&m);
		VScaleMatrix(&m, RectWidth(clip), yscale, 1.0);
		VTranslate(&m, clip.a.x, y_h, -1.0);
		if( radar_altimeter_scale == NULL )
			build_radar_altimeter_scale();
		vpath_stroke(radar_altimeter_scale, &m, w, whiteColor);

	}

	/* Draw reference mark: */
	Alib_drawLine(w, clip.a.x, y0+0.5, clip.b.x, y0+0.5, magentaColor);
	Alib_drawLine(w, clip.a.x, y0+0.5+1.0, clip.b.x, y0+0.5, magentaColor);
}


static void panel_lights_draw(craft * c, viewer * u)
{
	draw_Type *dd;
	Alib_Window   *w;
	int       rows, cols, row, col;
	double    width, height, x, y, cellH, cellW, cellX, cellY, fh, m;
	Alib_Pixel black;
	Alib_Rect rect;
	static _BOOL blink = FALSE;
	static double blink_toggle_time = 0.0;

	if( curTime > blink_toggle_time ){
		blink = ! blink;
		if( blink )
			blink_toggle_time = curTime + 0.1; /* off time */
		else
			blink_toggle_time = curTime + 0.2; /* on time */
	}

	w = u->w;
	Alib_setClipRect(w, &u->lights);
	
	dd = draw_new();

	width = RectWidth(u->lights);
	height = RectHeight(u->lights);
	x = u->lights.a.x;
	y = u->lights.a.y;

	cols = 2;
	rows = (LIGHTS_N + 1) / 2;
	cellW = width / cols;
	cellH = height / rows;
	fh = 0.30*cellH;
	m = 0.07*cellH;  /* cell margin */

	row = 0;
	col = 0;
	black = blackColor;
;
	if( gear_brakesEngaged(c) )
		c->damageBits |= FLAG_WHEELBRAKE;
	else
		c->damageBits &= ~FLAG_WHEELBRAKE;

	for( pptr = &panelVec[0]; pptr->mask != 0; ++pptr ){

		if( col >= cols )
			error_internal("col=%d >= cols=%d", col, cols);

		cellX = x + col * cellW;
		cellY = y + row * cellH;

		/*
			Draw cell background:
		*/

		if( (c->damageBits & pptr->mask) != 0
		&& (! pptr->blink || ! blink )
		){
			Alib_setRect(&rect, cellX + m, cellY + m, cellX + cellW - 2*m,
				cellY + cellH - 2*m);
			Alib_fillRect(w, &rect, magentaColor);
		}

		/*
			Draw cell label:
		*/
		draw_string_centered(u->v,
			cellX + 0.5*cellW, cellY + 0.5*cellH, fh,
			pptr->name, black);

		/*
			Draw cell border:
		*/
		/****
		draw_rect(dd, cellX + m, cellY + m, cellX + cellW - 2*m, cellY + cellH - 2*m);
		****/

		row++;
		if( row >= rows ){
			row = 0;
			col++;
		}
	}

	draw_stroke(dd, u->v, HUDColor);
	draw_free(dd);

	panel_radar_altimeter(u);
}


static double map_rpm_to_angle(int rpm)
{
	if( rpm < 20 )
		rpm = 20;
	else if( rpm > 120 )
		rpm = 120;
	
	return units_DEGtoRAD( (rpm - 20)*270.0 / 80.0 - 90 );
}


static void thrust_reverse_light(craft * c, viewer * u)
{
	static double blink_toggle_time = 0.0;
	static _BOOL blink = FALSE;

	int xsize, ysize, x, y, width, height, fh, fw, moving, fully_deployed;
	double xscale, yscale;
	Alib_Rect r;

	if( ! c->cinfo->hasThrustReverser )
		return;

	if( curTime > blink_toggle_time ){
		blink = ! blink;
		if( blink )
			blink_toggle_time = curTime + 0.2;
		else
			blink_toggle_time = curTime + 0.4;
	}

	xsize = RectWidth(u->engine);
	ysize = RectHeight(u->engine);

	xscale = xsize;
	yscale = ysize;

	x = u->engine.a.x + 0.82 * xscale;
	y = u->engine.a.y + 0.50 * yscale;

	width = 0.18*xscale;
	height = 0.18*yscale;

	fully_deployed = (c->thrust_reverse_pos < -0.4);
	moving = (c->thrust_reverse_pos < 0.9) && (c->thrust_reverse_pos > -0.4);

	Alib_setRect(&r, x, y, x + width, y + height);
	if( fully_deployed || (moving && !blink) )
		Alib_fillRect(u->w, &r, radarColor);

	Alib_drawRect(u->w, &r, blackColor);
	Alib_expandRect(&r, 1, 1);
	Alib_drawRect(u->w, &r, blackColor);

	fh = 0.25 * height;
	fw = fh;
	VDrawStrokeString(u->v,
		x + width/2 - 3*fw/2,
		y + height/2 - 0.02*yscale,
		"THR", 3, fh, blackColor);
	VDrawStrokeString(u->v,
		x + width/2 - 3*fw/2,
		y + height/2 + fh + 0.02 * yscale,
		"REV", 3, fh, blackColor);
}


static void panel_engine_draw(craft * c, viewer * u)
{
	draw_Type *dd;
	Alib_Window   *w;
	int       xsize, ysize, percent, percento, ab, x, y, rpm, fu;
	double    r, r1, r2, xc, yc, fh, co, si, a;
	char      s[32];
	Alib_Pixel     white;
	Alib_Rect      rect;

	xsize = RectWidth(u->engine);
	ysize = RectHeight(u->engine);
	x = u->engine.a.x;
	y = u->engine.a.y;
	white = whiteColor;

	dd = draw_new();
	w = u->v->w;
	Alib_setRect(&rect, x, y, x + xsize, y + ysize);
	Alib_setClipRect(w, &rect);
	
	percento = (int) ( (double)c->throttleComm / 32768.0 * 100.0 + 0.5);
	if (damage_isFunctioning(c, SYS_ENGINE1)) {
		percent = (int) (c->rpm * 100.0 + 0.5);
	}
	else {
		percent = 0;
	}
	ab = ((c->flags & FL_AFTERBURNER) == 0)? 0:1;

	r = 0.30*xsize;  /* body */
	r1 = 0.85*r; /* ticks */
	r2 = 0.65*r; /* numbers */
	xc = x + xsize/2;
	yc = y + r + 0.04*ysize;
	fh = 0.15*r;
	draw_circle(dd, xc, yc, r);
	for( rpm = 20; rpm <= 100; rpm += 10 ){
		a = map_rpm_to_angle(rpm);
		co = cos(a);
		si = sin(a);
		draw_segment(dd, xc + r*co, yc + r*si, xc + r1*co, yc + r1*si);
		if( rpm > 20 && rpm % 20 == 0 ){
			sprintf(s, "%d", rpm);
			draw_string_centered(u->v, xc + r2*co, yc + r2*si, fh, s, white);
		}
	}
	draw_arc(dd, xc, yc, 0.95*r, map_rpm_to_angle(85), map_rpm_to_angle(100));
	draw_string_centered(u->v, xc, yc + 0.20*r, 0.12*r, "RPM%", white);
	draw_pointer(dd, xc, yc, map_rpm_to_angle(percent), r2);

	/*
		Draw ordered power
	*/

	sprintf(s, "%3d%s", percento, ab? "AB" : "  ");
	draw_string_centered(u->v, xc, yc - 0.55*r, 0.18*r, s, white);
	draw_rect(dd, xc - 0.56*r, yc - 0.75*r, xc + 0.56*r, yc - 0.37*r);

	/*
		Print fuel total and fuel consumption rate
	*/

	fu = (int) (planes_fuelUsed(c) * 3600.0 / deltaT);
	if ( fu < 50 )
		fu = (fu + 3) / 5 * 5;
	else if ( fu < 500 )
		fu = (fu + 5) / 10 * 10;
	else
		fu = (fu + 50) / 100 * 100;

	draw_string_centered(u->v, x + xsize/2, y + 0.76*ysize, 0.05*xsize,
		"lb total   lb/hour", white);

	sprintf(s, "  %6d    %6d", ((int) c->fuel + 5)/10*10, (fu + 5)/10*10);
	draw_string_centered(u->v, x + xsize/2, y + 0.90*ysize, 0.05*xsize, s, white);

	draw_stroke(dd, u->v, whiteColor);
	draw_free(dd);

	thrust_reverse_light(c, u);
}


void panel_updateAndDraw(craft *c, viewer *u)
{
	Alib_Rect rect;
	Alib_setRect(&rect, 0, u->lights.a.y, gui_getWidth(u->gui), gui_getHeight(u->gui));
	Alib_setClipRect(u->w, &rect);
	Alib_fillRect(u->w, &rect, panelBackgroundColor);
	
	panel_lights_draw(c, u);
	radar_update(c, u);      /* Radar */
	radar_updateTEWS(c, u);  /* TEWS -- radar_update must be called first */
	adf_panel_draw(u);
	adf_draw(u);
	hsi_panel_draw(u);
	hsi_draw(u);
	panel_gear_and_flaps_draw(c, u);
	panel_engine_draw(c, u);
}