#ifndef PLANE_H
#define PLANE_H
/***************************************************************************
plane.h - Created by Peter Mauger 17/07/01
last modified 27/09/01

plane contains planestate object (contains all data on plane position, attitude
and control surfaces), as well as the functions required to manipulate it.
***************************************************************************/

#include "include.h"

/******************** The following functions manipulate the positional settings of the plane */

/* Init_Plane_Position_State initialises the internal variables of the position
* state part of the plane state
* returns:  an initialised planepos structure
*/
planeposstate Init_Plane_Position_State();

/* Init_Plane_Control_State initialises the internal variables of the control
* state part of the plane state
* inputs:  pcs->a variable for passing the plane control state out;
* returns: SERVOERROR if an error has occured in initialising the servo,
*	   NOERROR otherwise
*/
error Init_Plane_Control_State(planectrlstate *pcs);

/* Init_Plane_State initialises the internal variables of the plane state structure
* inputs:  ps->the variable for passing the main plane state structure
* returns: SERVOERROR if an error occured when initialising the servos,
*	   NOERROR otherwise
*/
error Init_Plane_State(planestate *ps);


/******************** The following functions manipulate the positional settings of the plane */

/* Get_Desired_Turn returns the desired turn variable stored in the plane state 
* structure
* inputs:  plane->contains positional info
* returns: the desired turn state of the plane (LEFT, RIGHT, STRAIGHT)
*/
turnstate Get_Desired_Turn(planestate plane);

/* Set_Desired_Turn sets the desired turn variable stored in the plane state
* structure. This variable determines which way the plane is trying to turn.
* inputs:  plane->contains positional info
*	   turn->the direction of the turn (LEFT, RIGHT, STRAIGHT)
*/
void Set_Desired_Turn(planestate *plane, turnstate turn);

/* Get_Desired_Altitude returns the desired altitude variable stored in the plane 
* state structure
* inputs:  plane->contains positional info
* returns: the desired altitude state of the plane (HIGHER, LOWER, LEVEL)
*/
altitudestate Get_Desired_Altitude(planestate plane);

/* Set_Desired_Altitude sets the desired altitude variable stored in the plane 
* state structure. This variable determines whether the plane is trying to 
* rise, fall or remain level.
* inputs:  plane->contains positional info
*	   turn->the altitude change required (HIGHER, LOWER, LEVEL)
*/
void Set_Desired_Altitude(planestate *plane, altitudestate altitude);

/* Get_Wplist returns the list of waypoints stored in the plane state structure
* inputs:  plane->contains positional info
* returns: the list of waypoints the plane is to travel to
*/
wplist Get_Wplist(planestate plane);

/* Store_Wplist stores a new set of waypoints in the plane state structure
* inputs:  plane->contains positional info
*	   waypoints->list of waypoints
*/
void Store_Wplist(planestate *plane, wplist waypoints);

/* Get_Altitude retrieves the current altitude information of the plane
* inputs:  plane->contains positional info
* returns: the altitude of the plane
*/
double Get_Altitude(planestate plane);

/* Set_Altitude sets the current altitude variable information of the plane
* inputs:  plane->contains positional info
*	   altitude->the current altitude of the plane
*/
void Set_Altitude(planestate *plane, double altitude);

/* Get_GPS_Message retrieves the message fragment stored in the plane structure
* inputs:  plane->contains the message fragment
* returns: the current message fragment
*/
message Get_GPS_Message(planestate plane);

/* Set_GPS_Message updates the message fragment stored in the plane structure
* inputs:  plane->contains the old message fragment
*	   mesg->the current message fragment
*/
void Set_GPS_Message(planestate *plane, message mesg);

/* Get_Curr_Pos retrieves the current coordinate information of the plane
* inputs:  plane->contains positional info
* returns: the current coordinates of the plane
*/
position Get_Curr_Pos(planestate plane);

/* Set_Curr_Pos sets the current coordinate information of the plane
* inputs:  plane->contains positional info
*	   pos->the current coordinates of the plane
*/
void Set_Curr_Pos(planestate *plane, position pos);

/* Get_Curr_Wp retrieves the coordinates of the current waypoint the plane
* is heading to.
* inputs:  plane->contains positional info
* returns: the coordinates of the current waypoint
*/ 
position Get_Curr_Wp(planestate plane);

/* Set_Curr_Wp establishes the next waypoint the plane is to fly to
* inputs:  plane->contains positional info
* 	   curr_wpnum->the number of the next waypoint
* returns: INVALIDWPNUM if curr_wpnum out of range of list, NOERROR otherwise
*/
error Set_Curr_Wp(planestate *plane, int curr_wpnum);

/* Store_Old_Position stores the old position so that it can be retrieved later
* (if an error occurs in getting the new position)
* inputs:  plane->contains positional info
*/
void Store_Old_Position(planestate *plane);

/* Restore_Old_Position restores the previously known position of the plane in
* the event that an error has ocurred in determining the new position
* inputs:  plane->contains positional info
*/
void Restore_Old_Position(planestate *plane);

/* Get_Curr_Heading retrieves the current heading information of the plane
* inputs:  plane->contains positional info
* returns: the currently known heading of the plane
*/
int Get_Curr_Heading(planestate plane);

/* Set_Curr_Heading sets the current heading information of the plane
* inputs:  plane->contains positional info
* 	   heading->the current heading of the plane
*/
void Set_Curr_Heading(planestate *plane, int heading);

/* Get_Req_Bearing retrieves the required bearing information of the plane
* inputs:  plane->contains positional info
* returns: the currently required bearing of the plane
*/
double Get_Req_Bearing(planestate plane);

/* Set_Req_Bearing sets the required bearing information of the plane
* inputs:  plane->contains positional info
* 	   heading->the currently required bearing of the plane
*/
void Set_Req_Bearing(planestate *plane, double bearing);

/* Store_Old_Heading stores the old heading so that it can be retrieved later
* (if an error occurs in getting the new heading)
* inputs:  plane->contains positional info
*/
void Store_Old_Heading(planestate *plane);

/* Restore_Old_Position restores the previously known heading of the plane in
* the event that an error has ocurred in determining the new heading
* inputs:  plane->contains positional info
*/
void Restore_Old_Heading(planestate *plane);

/* Get_Pitch retrieves the pitch information of the plane
* inputs:  plane->contains positional info
* returns: the pitch of the plane
*/
double Get_Pitch(planestate plane);

/* Set_Pitch sets the pitch information of the plane
* inputs:  plane->contains positional info
* 	   pitch->the pitch of the plane
*/
void Set_Pitch(planestate *plane, double pitch);

/* Get_Bank_Angle retrieves the bank angle information of the plane
* inputs:  plane->contains positional info
* returns: the bank angle of the plane
*/
double Get_Bank_Angle(planestate plane);

/* Set_Bank_Angle sets the bank angle information of the plane
* inputs:  plane->contains positional info
* 	   bank_angle->the bank angle of the plane
*/
void Set_Bank_Angle(planestate *plane, double bank_angle);

/* Get_Airspeed retrieves the airspeed information of the plane
* inputs:  plane->contains positional info
* returns: the airspeed of the plane
*/
double Get_Airspeed(planestate plane);

/* Set_Airspeed sets the airspeed information of the plane
* inputs:  plane->contains positional info
* 	   airspeed->the airspeed of the plane
*/
void Set_Airspeed(planestate *plane, double airspeed);

/* Get_Best_Correction retrieves the best correction information of the current
* turn of the plane
* inputs:  plane->contains positional info
* returns: the best correction of the current turn of the plane
*/
double Get_Best_Correction(planestate plane);

/* Set_Best_Correction sets the best correction information of the current turn
* of the plane
* inputs:  plane->contains positional info
* 	   correction->the current correction required by the plane
*/
void Set_Best_Correction(planestate *plane, double correction);

/* Get_Improve_Count retrieves the number of times the plane has failed to improve
* its heading
* inputs:  plane->contains positional info
* returns: the bearing improvement count of the plane
*/
int Get_Improve_Count(planestate plane);

/* Set_Improve_count updates the improve count
* inputs:  plane->contains positional info
* 	   count->the current number of times the plane has failed to improve its bearing
*/
void Set_Improve_Count(planestate *plane, int count);

/* Heading_Improvement determines whether the plane is making any improvement in heading
* given the current turn direction
* inputs:  plane->plane information     
*	   curr_correction->the current correction the plane needs to make
*/
void Heading_Improvement(planestate *plane, double curr_correction);

/* Get_Log returns the error log so new messages can be added 
* inputs:  plane->contains the error log
* returns: errorlog of all errors to date
*/
errorlog Get_Log(planestate plane);

/* Set_Log updates the messages in the error log with new messages
* inputs:  plane->contains the old log for overwriting
* 	   log->conatins the new set of error messages
*/
void Set_Log(planestate *plane, errorlog log);

/* Log_Event performs the procedure required to log an event
* inputs:  plane->contains old log and positional data
*	   event->identifies the event that occured
*/
void Log_Event(planestate *plane, error event);

/* Add_Event adds an event to the message log. Message is not added if capacity
* has been reached.
* inputs:  log->contains the old error messages (will be added to)
*	   tag->an identifier for the event (type error)
*	   gps_pos->current position of the aircraft
*	   wp_pos->position of current waypoint
*	   heading->current heading of the aircraft
*	   bearing->bearing required to reach current waypoint
*/
void Add_Event(errorlog *log, error tag, position gps_pos, position wp_pos, int heading, double bearing);

/* Upload_Error_Log uploads the error log to a PC
* inputs:  plane->contains the log of all events that have occured
*	   type->the grouping/order of the upload (chronological order or event grouping)
* returns: SENDERROR if an error occured during the send (resend the data!)
*	   NOERROR otherwise
*/
error Upload_Error_Log(planestate plane, upltype type);

/* Convert_Tag2Event changes an error tag into an event string
* If any new errors are added, this function must be updated
* inputs:  tag->the event label
*	   event_str->the string which defines the event
*/
void Convert_Tag2Event(error tag, char *event);


/******************** The following functions update the servo states and settings of the plane */

/* Get_Ctrl_Surface returns the relevant control surface information from the 
* plane control struct
* inputs:  plane->contains the control information
*	   ctrl_surface_name->the label of the control surface that is to be returned
*	   ctrl_surface->the control surface being returned
* returns: INVALIDSERVO if the servo label is out of range
*	   NOERROR otherwise
*/
error Get_Ctrl_Surface(planestate plane, servoconsts ctrl_surface_name, ctrlsurface *ctrl_surface);

/* Set_Ctrl_Surface stores new control surface information for the surface
* inputs:  plane->contains the control information
* 	   ctrl_surface->the control surface to be updated
*	   ctrl_surface_name->the name of the ctrl_surface to be updated
* returns: INVALIDSERVO if the servo label is out of range
*	   NOERROR otherwise
*/
error Set_Ctrl_Surface(planestate *plane, ctrlsurface ctrl_surface, servoconsts ctrl_surface_name);

/* Get_Rudder_State retrieves the current state of the rudder
* inputs:  plane->contains the control information
* returns: the turn state of the rudder (LEFT, RIGHT, STRAIGHT);
*/
turnstate Get_Rudder_State(planestate plane);

/* Set_Rudder_State sets the current state of the rudder
* inputs:  plane->contains control information
*	   rudder->the turn state required of the rudder
*/
void Set_Rudder_State(planestate *plane, turnstate rudder);

/* This function will change the servos to reflect the current states in the 
* plane control structure. If any new surfaces are required then this function
* must be updated.
* inputs:  plane->plane structure containing the required servo settings
* returns: error occured or not (SERVOERROR if failed, NOERROR otherwise)
*/
error Update_Servos(planestate *plane);

#endif
