/*
 *  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.
 */

/**
 * Plane management data structures and routines. Basically, the core of all
 * tools needed for the ACM simulation are defined here.
 * 
 * @author Riley Rainey
 * @license GNU GPL
 * @version $Date: 2020/01/08 06:10:19 $
 * @file
 */

#ifndef _pm_h
#define _pm_h

#include "../V/Vlibmath.h"
#include "../V/VObjects.h"
#include "../util/gui.h"
#include "inventory.h"
#include "manifest.h"
#include "scale.h"
#include "air.h"
#include "zones.h"

#ifdef pm_IMPORT
	#define EXTERN
#else
	#define EXTERN extern
#endif

#ifdef WINNT
	typedef BOOL _BOOL;
#else
	typedef int _BOOL;
#endif

#ifndef TRUE
	#define TRUE    1
	#define FALSE   0
#endif

/*
 *  Each rendering window has a _viewer structure which may be in one
 *  of several states.
 */

#define ViewerStateNormal         0  /* just a plane that we control */
#define ViewerStateBrowsing       1  /* not yet associated with an entity */
#define ViewerStatePiggyback      2  /* a stealth glued to an entity */
#define ViewerStateControlPending 3  /* requested control of an entity */
//#define ViewerStateControlling    4  /* have control of another entity (FIXME: not used) */

/**
 * Cockpit view from a specific aircraft is rendered through this object.
 */
typedef struct viewer {

	/** Linked list of all active rendering viewers. */
	struct viewer *vl_next;

	/**
		Next viewer attached to this craft. Since usually there is
		just only one viewer per craft, this field is usually NULL.
	*/
	struct viewer *next;

	/** One of the ViewerState* constants. */
	int viewer_state;

	/** Associated aircraft. */
	struct craft *c;
	
	/** Associated craft when in stealth mode. */
	struct craft *watchedCraft;
	
	/**
	 * The window. Users' input and window events are read from here, but
	 * drawing is always performed into the z-buffer first.
	 */
	gui_Type *gui;

	/** If the window has focus, then may receive keyboard and mouse input. */
	_BOOL     hasFocus;
	
	/** If users' input is currently accepted or "don't touch anything" mode. */
	_BOOL     hasComm;
	
	/** 2-D off-screen drawing device with z-buffer. */
	Alib_Window  *w;
	
	/** 3-D off-screen drawing device bound to the z-buffer. */
	Viewport *v;
	
	/** Cockpit view direction as a vector in AXYZ. */
	VPoint    viewDirection;
	
	/** "Up" direction in AXYZ. */
	VPoint    viewUp;

	/** Organize HUD drawing around (xCenter,hud_yCenter). */
	int       hud_yCenter;

	/** Zoom factor (percent). */
	int       zoom;

	/**
	 * If HUD mode, otherwise it is "classic panel mode". This is a
	 * read-only flag, as it set by (indows_resizePlayerWindow().
	 */
	_BOOL  hud_mode;

	/** Classic mode: timer and APS lights stripe area. */
	Alib_Rect      stripe;
	/** Classic mode: turn and slip indicator area. */
	Alib_Rect      turn;
	/** Classic mode: air speed indicator area. */
	Alib_Rect      anemometer;
	/** Classic mode: attitude indicator area. */
	Alib_Rect      attitude;
	/** Classic mode: altimeter indicator area. */
	Alib_Rect      altimeter;
	/** Classic mode: vertical speed indicator area. */
	Alib_Rect      vsi;

	/** Alarm and status lights area. */
	Alib_Rect      lights;
	/** Radard altimeter area. */
	Alib_Rect      radar_altimeter;
	/** Tuner area. */
	Alib_Rect      tuner;
	/** Area shared by HSI, ADF and radar. */
	Alib_Rect      indicator;
	/** Gear, flaps and max bank area. */
	Alib_Rect      gear;
	/** Engine RPM and throttle area. */
	Alib_Rect      engine;

	/** HUD, altitude stripe. */
	scale_Type altScale;
	/** HUD, air speed stripe. */
	scale_Type velScale;
	/** HUD, heading stripe. */
	scale_Type hdgScale;

	/** HUD, overall x scale factor. */
	double    xscaleFactor;
	/** HUD, overall y scale factor. */
	double    yscaleFactor;
	
	/** Previous radar frame. */
	Alib_Segment   radarImage[1024];
	
	int       radarImageCount;

	/** First drawn DIS entity in RM_DIS_BROWSE. */
	int       browseBase;
	
	int       browseSelectedItem;
	
	unsigned long browseClickTime;

	/*
		Private data structures handled by the corresponding modules:
	*/
	void     *hud;              /* see hud module */
	void     *magnetic_compass; /* see magnetic_compass module */
	void     *hsi;              /* see hsi module */
	void     *adf;              /* see adf module */
	void     *sounds;           /* see sounds module */
	void     *inst;             /* see instruments module */
	void     *terminal;         /* see terminal module */
	void     *prompt;           /* see prompt module */
} viewer;


/**
 * Radar tracking information.
 */
typedef struct {
	int       beamID;           /* index number of beam */
	VPoint    rel;              /* location relative to radar set */
	double    d;                /* distance to target (ft) */
	int       targetID;         /* craft id of target */
	int       locked;           /* 1=we have a "lock" */
	int       altDisplay_kft;   /* altitude readout (ft x 1000) */
	int       headingDisplay_deg; /* ground track of target */
	int       x, y;
} radarInfo;


/** Alias for the (quite obscure for me) "trihedral" craft struct field. */
#define AXYZtoNED trihedral

/**
 * State of the aircraft. Also missiles, drop bombs, cannon bursts, runways,
 * land features and explosion effects all share this same struct, although some
 * fields may have a slightly different meaning or aren't used at all.
 * 
 * The involved reference frames are all right-handled:
 * 
 * - XYZ:     world reference frame.
 * 
 * - AXYZ:    aircraft reference frame, center in CM, x longitudinal
 * 			  pointing forward, y pointing rightward and z pointing
 * 			  downward.
 * 
 * - NED:     center=aircraft CM, x toward geographic north, y east,
 * 			  z downward.
 * 
 * The involved matrices are:
 * 
 * - c->trihedral or c->AXYZtoNED is a pure rotational matrix from AXYZ to NED.
 * 
 * - c->XYZtoNED is a roto-translational matrix from XYZ to NED.
 * 
 * The Euler angles, giving the angular rotations to pass from NED to AXYZ,
 * are so normalized (sorted in order of application to obtain the actual
 * aircraft orientation):
 * 
 * - c->curHeading rotation around z, [0,2*PI[
 * - c->curPitch   rotation around y, [-PI/2,PI/2]
 * - c->curRoll    rotation around x, [-PI,PI]
 * 
 * 
 * In some cases, this data structure belongs to an array; in other cases
 * (surface objects) a double-linked list of dynamically allocated items is
 * used instead. That's why there are both index-related fields (pIndex) and
 * list-related fields as well (next, prev).
 * 
 * An update() and kill() fields points to the specific dynamic update and delete
 * routines mostly like this struct was a class in a object-oriented language,
 * but this program does not go any further on this paradigm.
 */
typedef struct craft {
	
	/** Index of this structure in the container vector. */
	int       pIndex;
	
	/** Previous craft in a doubly-linked list. */
	struct craft *prev;
	
	/** Next craft in in a doubly-linked list. */
	struct craft *next;
	
	/** Status flags, see FL_* constants. */
	unsigned long flags;
	
	/** Craft type, see CT_* constants. */
	int       type;
	
	/** Name of the player. */
	char      name[32];
	
	/** DIS force this plane belongs to. */
	DISForce  force;
	
	/** Creation time (simulation time, s). */
	double    createTime;
	
	/**
	 * For real local players, the zone the craft is currently flying over.
	 * For runways and features implemented through this same data struct,
	 * it is the zone from which that item was loaded from.
	 * For munitions and remote crafts it is set to NULL.
	 */
	zone_Type *zone;
	
	/**
	 * List of viewers windows looking through the windshield of this craft.
	 */
	viewer   *vl;
	
	/**
	 * Transforms from aircraft XYZ to NED. The self-explaining macro "AXYZtoNED"
	 * could also be used instead.
	 */
	VMatrix   trihedral;
	
	/** Velocity vector in NED (ft/s). */
	VPoint    Cg;
	
	/** Airspeed (ft/s). */
	double    VT;
	
	/** Indicated air speed (ft/s). */
	double    IAS;
	
	/** Position in geocentric frame XYZ (m). */
	VPoint    Sg;
	
	/** Position as geodetic coordinates. */
	earth_LatLonAlt w;
	
	/** Properties of the surrounding air. */
	air_Properties air;
	
	/** Current Mach number. */
	double    mach;             /* current Mach number */
	
	/**
	 * Altitude over the terrain (m).
	 * BEWARE: this field is for internal use only of the terrain module;
	 * client code should invoke terrain_altitude() instead.
	 */
	double    terrain_altitude;
	
	/**
	 * Scheduled update of the local terrain altitude. For internal use only of
	 * the terrain module.
	 */
	double    terrain_altitude_timeout;
	
	/** Geocentric to NED transformation. */
	VMatrix   XYZtoNED;
	
	/** Euler angle of heading vs. NED (RAD). */
	double    curHeading;
	
	/** Euler angle of pitch vs. NED (RAD). */
	double    curPitch;
	
	/** Euler angle of bank vs. NED (RAD). */
	double    curRoll;
	
	/** Roll rate (RAD/s). */
	double    p;
	
	/** Pitch rate (RAD/s). */
	double    q;
	
	/** Yaw rate (RAD/s). */
	double    r;
	
	/** Angle of attack (RAD). */
	double    alpha;
	
	/** Angle of sideslip (RAD). */
	double    beta;
	
	/** G-force in aircraft frame (units of "g"). */
	VPoint    G;
	
	/** Acceleration in aircraft frame (ft/s^2). */
	VPoint    linAcc;
	
	/** Last interval's Sg value (m). Unsure if still needed. */
	VPoint    prevSg;

	/** Pilot's pitch command [-1.0,1.0]. */
	double    pitchComm;
	
	/** Pilot's roll command [-1.0,1.0]. */
	double    rollComm;
	
	/** Pilot's steer command [-1.0,1.0]. */
	double    steerComm;
	
	/** Pilot's rudder command [-1.0,1.0]. */
	double    rudderComm;
	
	/** Pilot's throttle command [0,32768]. */
	int       throttleComm;

	/** Elevator position [-1.0,1.0]. */
	double    Se;

	/** Ailerons position [-1.0,1.0]. */
	double    Sa;

	/** Rudder position [-1.0,1.0]. */
	double    Sr;
	
	/** Pitch trim setting. */
	double    SeTrim;
	
	/** Roll trim setting. */
	double    SaTrim;
	
	/** Current thrust value (lbf). */
	double    curThrust;
	
	/** Pilot's thrust reverser command. */
	_BOOL     thrust_reverse_on;
	
	/**
	 * Thrust reverser factor [-0.5 .. +1.0]. The actual thrust that pushes the
	 * aircraft is a vector directed as the x axis and with module
	 * curThrust*thrust_reverse_pos, possibly yielding a negative value.
	 */
	double    thrust_reverse_pos;
	
	/** Actual flaps position (RAD). */
	double    curFlap;
	
	/** Flaps command position (RAD). */
	double    flapSetting;

	/** Current speed brake position (RAD). */
	double    curSpeedBrake;
	
	/** Current target speed brake setting (RAD). */
	double    speedBrakeSetting;
	
	/** Landing gear module state - see gear.h. */
	void *    gear;
	
	/** Thrust setting [0,32768]. */
	int       throttle;
	
	/** Engine RPM [0.0,1.0]. */
	double    rpm;
	
	/** Current fuel on board (lb). */
	double    fuel;
	
	/** Payload (lb). */
	double    payload;

	/** Bit flags of damaged subsystems. */
	long      damageBits;
	
	/** Damage pts that can be absorbed. */
	long      structurePts;
	
	/** Fuel leakage rate (lb/s). */
	double    leakRate;
	
	/** Damage induced roll. */
	double    damageCL;
	
	/** Damage induced pitch. */
	double    damageCM;

	/** Shared panel current mode: radar, HSI or ADF. */
	int       radarMode;
	
	/** General craft information. */
	craftType *cinfo;

	/** Time of next Radar frame. */
	double    nextRadarTime;
	
	/** Our primary "threat". */
	short     curRadarTarget;
	
	/** Distance to primary target [ft]. */
	double    targetDistance;
	
	/** Closure rate on primary target [ft/s]. */
	double    targetClosure;
	
	/** Used by radar and missile. */
	VPoint    relPos[manifest_MAXPLAYERS];
	
	/** Radar strength seen by us from other craft. */
	double    rval[manifest_MAXPLAYERS];
	
	/** Radar target information: relative positions of possible targets. */
	radarInfo rinfo[32];
	
	/** Number of entries used in rinfo. */
	int       rtop;
	
	/** Strings in upper left corner of HUD reserved for weapons' status. */
	char     *leftHUD[6];
	
	/** Strings in upper right corner of HUD reserved for radar target info. */
	char     *rightHUD[6];
	
	/** Index of currently selected weapon in wtbl[]. */
	int       curWeapon;
	
	/** What's at each weapon station. */
	weaponStation station[manifest_STATIONS];
	
	/**
	 * Handle assigned by dis_if module to this craft to retrieve associated
	 * DIS state.
	 */
	int       disId;

	/*
	 * Magnetic field data at the location of the aircraft. Since the
	 * calculation is a bit expensive, we store here the last current value
	 * calculated and the time we expect it to be updated; the indicated value
	 * smoothly follows the current one.
	 */
	
	/**
	 * If HUD and HSI have to display magnetic header rather than geographic
	 * heading. Always true in "classic instruments" mode. Always false for
	 * drones (no need to calculate Earth's magnetic field for them).
	 */
	int        showMag;
	
	/**
	 * Latest calculated magnetic field components in NED (nT).
	 * This field periodically updated only if showMag is true.
	 */
	VPoint     actualMagneticField;
	
	/**
	 * Latest calculated magnetic variation, positive west (RAD).
	 * This field periodically updated only if showMag is true.
	 */
	double     actualLocalVAR;
	
	/**
	 * Scheduled update of the local magnetic field data (s). Normally this is
	 * done every 10 s, but at higher speed an update is forced early.
	 */
	double     updActualMagneticField;
	
	/**
	 * Indicated magnetic field components in NED (nT). Smoothly follows the
	 * latest calculated value.
	 */
	VPoint     indicatedMagneticField;
	
	/**
	 * Indicated local magnetic variation, positive west (RAD). Smoothly follows
	 * the latest calculated value.
	 */
	double     indicatedLocalVAR;
	
	/**
	 * When to update the indicated magnetic field so that it smoothly follows
	 * the actual calculated value (s).
	 */
	double     updIndicatedMagneticField;

	/**
	 * Drone module private data, set when this aircraft is created as a drone
	 * or a player enables the drone mode -- see drone module.
	 */
	void      *drone;
	
	/** Autopilot System private data -- see aps module. */
	void      *aps;
	
	/** Effects private data -- see effects module. */
	void      *effects;

	/* Munition handling (see dis_if.c, ccip.c, missile.c): */
	double    offset;
	long      tracerMod;
	int       tracerVal;
	double    interval;
	short     rounds;
	int       owner;
	double    armTimer;
	
	/**
	 * Internal state update procedure bound to this specific craft.
	 * Local entities must also send their new state to the DIS module, while
	 * for remote entities the state can be retrieved from the DIS module.
	 * May return the kill reason, or NULL if still alive.
	 */
	char *(*update)(struct craft *c);
	
	/**
	 * Kill procedure to call before removal bound to this specific craft.
	 * The kill reason can be set by the update procedure itself, or by client.
	 */
	void (*kill)(struct craft *c, char *reason);

} craft;


/*
 *  Craft type definitions
 */

#define CT_FREE     0           /* an unused craft entry */
#define CT_PLANE    1           /* a player */
#define CT_MISSILE  2           /* an air to air missile */
#define CT_CANNON   3           /* a stream of cannon fire */
#define CT_SURFACE  4           /* surface object (e.g. a runway) */
//#define CT_CHASER 5           /* a non-player "watcher" chasing a plane (FIXME: not used) */
#define CT_DRONE    6           /* a target drone */
#define CT_EXPLOSION    7       /* an explosion */
#define CT_DIS_PLANE    8       /* external player (on different server) */
#define CT_DIS_MUNITION 9       /* external tracked munition */
#define CT_DIS_CANNON   10      /* external untracked munition (cannon) */
#define CT_RESERVED     11      /* a reserved, uninitialized entry */
#define CT_DIS_STEALTH  12      /* a place-holder for stealths */
#define CT_BOMB         13      /* gravity bomb */

/*  Flag word definitions */

#define FL_RECORD       (1<<0)    /* activate recording function */
#define FL_AFTERBURNER  (1<<1)    /* afterburner state */
#define FL_HAS_GYRO     (1<<2)    /* missile is gyroscope equiped */
#define FL_FIXED_OBJECT (1<<3)   /* fixed (surface) object */
#define FL_CHASE_VIEW   (1<<4)   /* chase plane view */
#define FL_BLACK_BOX    (1<<5)   /* object is from a black box recording */
#define FL_BALLISTIC    (1<<6)   /* munition has no target */
#define FL_RADAR_MODE_CHANGE (1<<7) /* set when user changes radar mode */
#define FL_END_GAME_DRONE (1<<8) /* drone in CALSPAN end-game mode */

/* Radar mode definitions. Since radar+TEWS, ADF and HSI+HSI panel all share
 * the same slots in the panel of the radar, these constants are global rather
 * than being defined inside their respective modules radar.h, adf.h and hsi.h. */

#define RM_OFF      0       /* radar is off */
#define RM_STANDBY  1       /* standby */
#define RM_NORMAL   2       /* track while scan */
#define RM_ACM      4       /* 20x30 acm */
#define RM_STT      8       /* single target track */
#define RM_HSI     16       /* HSI mode */
#define RM_ADF     32       /* ADF mode */
#define RM_DIS_BROWSE 64    /* browse entities */

/** Linked list of all rendering windows (normally only one). */
EXTERN viewer *vl_head;

/** Number of players recording info. */
EXTERN int recordCount;

/** Number of active entries in ptbl. */
EXTERN int ptblCount;

/** Number of chasers. */
EXTERN int ctblCount;

/** Departure timestamp (seconds since 1970-01-01T00:00:00). */
EXTERN int    departure_timestamp;

/**
 * Simulation time (s). Or, time elapsed since simulation started.
 * Added to the departure timestamp gives the current (simulated) timestamp.
 */
EXTERN double curTime;

/** List of surface objects: runways, features -- see zones module. */
EXTERN craft *stbl;

/** Players table, including drones, locale and remote. */
EXTERN craft ptbl[manifest_MAXPLAYERS];

/** Missiles and cannon bursts table, locale and remote. */
EXTERN craft mtbl[manifest_MAXPROJECTILES];

/**
 * Location of the force base for resupply. The index is one of the DISForce
 * constants. Currently only the 1 (DISForceFriendly) and 2 (DISForceOpposing)
 * are set with the team locations read from the starting zone, if available.
 * The default force base is located at 0N 0E!
 */
EXTERN earth_LatLonAlt forceBaseLocation[4];

/**
 * Dynamics update period (s). That is, aerodynamic forces, gear dynamics and
 * in general the craft state update are performed with frequency 1/deltaT Hz
 * which is (or should be) much higher than the frame rate of the renderer to
 * prevent numerical instability issues.
 */
EXTERN double deltaT;

/** 0.5 * deltaT * deltaT */
EXTERN double halfDeltaTSquared;

/* Colors look-up table index for some colors of general usage. */
EXTERN int HUDColor;
EXTERN int whiteColor;
EXTERN int blackColor;
EXTERN int yellowColor;
EXTERN int redColor;
EXTERN int magentaColor;
EXTERN int radarColor;
EXTERN int panelBackgroundColor;

/** Cloud base altitude (ft). */
EXTERN double clouds_base;

/** Cloud top altitude (ft). No clouds if clouds_top is less or equal to clouds_base. */
EXTERN double clouds_top;

/** Set by arcade -a switch: never run out of ammunitions. */
EXTERN int arcadeMode;

EXTERN double end_game_threshold_meters;
EXTERN int end_game_mode;
EXTERN int transferEntityIdBits;
EXTERN dis_entity_id subjectEntityID;
EXTERN int subjectEntitySpecified;     /* =1 if subject entity was
										specified on the command line */
/** Pilot eye dist. from screen (cm). */
EXTERN double eye_to_screen_cm;

/** Downward view angle over the nose (RAD). */
EXTERN double downward_view_angle_rad;

/** State of the zones module. */
EXTERN zones_Type *zones;

EXTERN void pm_calcGForces(craft * c, VPoint * f, double w);

/**
 * Performs flight dynamics calculations. Return NULL on success,
 * otherwise return a string reporting the reason why the aircraft
 * was destroyed.
 */
EXTERN char * pm_flightCalculations(craft * c);

/**
 * Calculate Euler angles c-&gt;curRoll, c-&gt;curPitch and c-&gt;curHeading
 * from the matrix c-&gt;trihedral. It is a shorter version of
 * 
 * VMatrixToEuler(&c-&gt;AXYZtoNED, &c-&gt;curRoll, &c-&gt;curPitch, &c-&gt;curHeading);
 */
EXTERN void pm_euler(craft * c);

/*
	These functions return the program idea of normalized Euler's
	angles, as explained above describing the "craft" data type.
*/
EXTERN double pm_normalize_roll(double roll);
EXTERN double pm_normalize_pitch(double pitch);
EXTERN double pm_normalize_yaw(double yaw);

EXTERN double pm_heading(VPoint * x);

EXTERN void pm_hud_strings_alloc(craft *c);
EXTERN void pm_hud_strings_free(craft *c);

EXTERN void pm_thrust_reverse_toggle(craft *c);

EXTERN void pm_after_burner_toggle(craft *c);
EXTERN void pm_after_burner_on(craft *c);
EXTERN void pm_after_burner_off(craft *c);

/**
 * Return current magnetic heading of the aircraft. Also updates the fields
 * related to the magnetic field.
*/
EXTERN double pm_mag_heading(craft * c);

#undef EXTERN
#endif
