#include <cstdint>

#pragma once

typedef bool		PMC_BOOL;
typedef uint8_t		PMC_BYTE;
typedef uint16_t	PMC_WORD;
typedef uint32_t	PMC_DWORD;
typedef uint64_t	PMC_LWORD;
typedef uint8_t		PMC_USINT;
typedef uint16_t	PMC_UINT;
typedef uint32_t	PMC_UDINT;
typedef uint64_t	PMC_ULINT;
typedef int8_t		PMC_SINT;
typedef int16_t		PMC_INT;
typedef int32_t		PMC_DINT;
typedef int64_t		PMC_LINT;
typedef float		PMC_REAL;
typedef double		PMC_LREAL;

namespace PMC
{
    /// @brief Enum for the source of the trigger for WaitUntil command
    enum class TRIGGERSOURCE : PMC_USINT
    {
		/// @brief Time delay trigger mode
		TIME_DELAY,
		/// @brief external digital input trigger mode
		EXTERNAL_DI,		
		/// @brief fieldbus digital input trigger mode		
		FIELDBUS_DI,		
		/// @brief command label trigger mode	
		CMD_LABEL,		
		/// @brief displacement trigger mode		
		DISPLACEMENT
    };

	/// @brief Enum for when the WaitUntil command should start monitoring	
	enum class WAITUNTILSTARTOPTION : PMC_USINT
	{		
		/// @brief Starts monitoring when the command is executed (removed from the buffer)
		STARTATEXECUTION,
		/// @brief Starts monitoring when the command is received (added in the buffer)	
		STARTATRECEIVED,	
		/// @brief Starts monitoring for the finish condition only after the specified start condition has been met	
		SPECIFYSTARTCONDITION
	};

	/// @brief enum for possible trigger edge types for digital inputs	
	enum class TRIGGEREDGETYPE : PMC_USINT
	{	
		/// @brief triggers on the rising edge
		RISING_EDGE,
		/// @brief triggers on the falling edge
		FALLING_EDGE,
		/// @brief triggers when source value is 1
		IS_ONE,
		/// @brief triggers when source value is 0
		IS_ZERO
	};
	
	/// @brief enum for when to trigger during command label delay method
	enum class TRIGGERCMDLABELTYPE : PMC_USINT
	{
		/// @brief triggers at the start of command
		CMD_START,
		/// @brief triggers when the command has finished
		CMD_FINISH,
		/// @brief triggers during command execution
		CMD_EXECUTING
	};

	/// @brief enum for defining trigger command label's command type
	enum class TRIGGERCMDTYPE : PMC_USINT
	{	
		/// @brief The command is a standard motion command such as linear motion, arc motion, etc.
		MOTION_COMMAND,
		/// @brief The command is a run macro motion command
		RUNMACRO_COMMAND
	};
	
	/// @brief enum for trigger type during displacement trigger method
	enum class TRIGGERDISPLACEMENTTYPE : PMC_USINT
	{
		/// @brief triggers when displacement (ax+by, or only x, or only y) is greater than threshold
		GREATER_THAN,
		/// @brief triggers when displacement (ax+by, or only x, or only y) is less than threshold
		LESS_THAN,
		/// @brief triggers when going from less than threshold to greater than threshold
		POSITIVE_CROSS,
		/// @brief triggers when going from greater than threshold to less than threshold
		NEGATIVE_CROSS
	};

	/// @brief enum for trigger mode during displacement trigger method
	enum class TRIGGERDISPLACEMENTMODE : PMC_USINT
	{
		/// @brief monitoring X position only
		X_ONLY,
		/// @brief monitoring Y position only
		Y_ONLY,
		/// @brief monitoring by an arbitrary line
		AX_BY
	};

	/// @brief can choose between position and force feedback in the GetXBOTStatus command
	enum class FEEDBACKOPTION : PMC_USINT
	{
		/// @brief provides position data in the command reply
		POSITION,
		/// @brief provides force data in the command reply
		FORCE
	};

	/// @brief reply from the PMC for a given command
	enum class PMCRTN : PMC_UINT
	{
		/// @brief command accepted
		ALLOK = 0,
		/// @brief PMC failed to reply, please resend command
		SYSTEMERROR = 0X0001,
		/// @brief PMC is in an incorrect state for this command. (For example, not activated)
		WRONGPMCSTATE = 0x2000,
		/// @brief Do not have the required mastership for this command
		NOMASTERSHIP = 0x2001,
		/// @brief mastership did not provide a response
		MASTERSHIP_TIMEOUT = 0x2002,
		/// @brief Group command rejected due to wrong group state
		WRONG_GROUP_STATE = 0x2003,
		/// @brief Macro command rejected due to wrong macro state
		WRONG_MACRO_STATE = 0x2004,
		/// @brief Wrong digital input / output state
		WRONG_DIGITAL_IO_STATE = 0x2005,
		/// @brief wrong flyway state
		WRONG_FLYWAY_STATE = 0x2006,
		/// @brief Failed to find a routing solution for auto driving
		NO_ROUTING_SOLUTION = 0x2008,
		/// @brief Failed to find a routing solution for auto driving
		COMMUNICATION_TIMEOUT = 0x2009,
		/// @brief missing license
		NO_LICENSE = 0x200A,
		/// @brief mover stereotype is not defined
		UNDEFINED_STEREOTYPE = 0x200B,
		/// @brief Xbot state incorrect for this command. (For example, not levitated)
		WRONGXBOTSTATE = 0x3000,
		/// @brief Parameters for this command are invalid
		INVALIDPARAMS = 0x4000,
		/// @brief wrong queue state
		WRONG_QUEUE_STATE = 0x5000,
		/// @brief The zone is in the wrong state to perform this operation
		WRONG_ZONE_STATE = 0x5001,
		/// @brief An XBot is located on the zone boundary
		ZONE_NOT_AVAILABLE = 0x5002,
		/// @brief only used for code generation, not an actual command for the PMC
		CODE_GENERATION_ONLY = 0xFFFE,
		/// @brief the command ID is invalid
		INVALIDCOMMAND = 0xFFFF
	};
	
	/// @brief XBot state enum
	enum class XBOTSTATE : PMC_USINT
	{
		/// @brief XBot not detected by the PMC
		XBOT_UNDETECTED = 0,
		/// @brief XBOT is landed
		XBOT_DISCOVERING,
		/// @brief XBOT is landed
		XBOT_LANDED,
		/// @brief XBOT is idling (levitated)
		XBOT_IDLE,
		/// @brief XBOT is disabled
		XBOT_DISABLED,
		/// @brief XBOT is in motion
		XBOT_MOTION,
		/// @brief XBOT is waiting for a trigger
		XBOT_WAIT,
		/// @brief XBOT is attempting to stop
		XBOT_STOPPING,
		/// @brief XBOT detected an obstacle and is waiting for obstacle to clear
		XBOT_OBSTACLE_DETECTED,
		/// @brief XBOT is hold position due excessive error during motion
		XBOT_HOLDPOSITION,
		/// @brief XBOT stopped and will not automatically resume
		XBOT_STOPPED,
		/// @brief XBOT is in stream motion
		XBOT_RESERVED,
		/// @brief XBOT is in asynchronous motion (automatically driven to target)
		XBOT_RESERVED1,
		/// @brief reserved
		XBOT_RESERVED2,
		/// @brief XBOT has an error
		XBOT_ERROR,
		/// @brief XBOT is not installed
		XBOT_UNINSTALLED
	};

	/// @brief PMC Status Enum
	enum class PMCSTATUS : PMC_USINT
	{
		/// @brief PMC is booting up
		PMC_BOOTING = 0,
		/// @brief PMC is inactive (XBOTs deactivated)
		PMC_INACTIVE,
		/// @brief PMC is starting to activate
		PMC_ACTIVATING,
		/// @brief Reserved
		PMC_RESERVED,
		/// @brief Reserved
		PMC_SERVICE,
		/// @brief PMC in fully controlled mode
		PMC_FULLCTRL,
		/// @brief PMC in intelligent control mode
		PMC_INTELLIGENTCTRL,
		/// @brief PMC is deactivating
		PMC_DEACTIVATING,
		/// @brief PMC is handling an error and recording snapshots
		PMC_ERRORHANDLING,
		/// @brief PMC is in the error state
		PMC_ERROR,
	};

	/// @brief Multi-PMC Border Status Enum
	enum class BORDERSTATUS : PMC_USINT
	{	
		/// @brief The flyway link between this border is not connected
		DISCONNECTED = 0,
		/// @brief The flyway link between this border is connected, but it is not yet ready to receive xbots
		NOTREADY,
		/// @brief The flyway link at this border is connected and it is ready to receive xbots
		READY
	};

	/// @brief Motion position mode Enum	
	enum class POSITIONMODE : PMC_USINT
	{
		/// @brief Absolute positioning
		ABSOLUTE_MOTION = 0,
		/// @brief Relative positioning
		RELATIVE_MOTION
	};

	/// @brief Can choose between
	enum class CAMMODE : PMC_USINT
	{
		/// @brief automatically trigger the cam motion when the master xbot is inside the cam region
		AutoStart = 0,
		/// @brief the profile is unwound and repeats cyclicly, such that the cam profile covers the range from -infinity to + infinity for the master axis
		Cyclic = 1,
		/// @brief the cam stops automatically if the master axis exits the defined cam region, and does not start again if the master axis re-enters the cam region
		SingleStart = 2,
	};

	/// @brief Select the cam engagement direction
	enum class CAMRATCHETDIRECTION : PMC_USINT
	{
		/// @brief The cam is engaged whether the master axis value is changing in the forward (positive) or backward (negative) direction
		BOTH_DIRECTIONS = 0,
		//future editions will add forward only and reverse only
	};

	/// @brief Linear path type Enum
	enum class LINEARPATHTYPE : PMC_USINT
	{
		/// @brief Direct motion
		DIRECT = 0,
		/// @brief X motion first, then Y motion
		XTHENY,
		/// @brief Y motion first, then X motion
		YTHENX
	};

	/// @brief Arc direction Enum
	enum class ARCDIRECTION : PMC_USINT
	{
		/// @brief Clockwise motion
		CLOCKWISE = 0,
		/// @brief Counter-clockwise motion
		COUNTERCLOCKWISE
	};

	
	/// @brief Arc type Enum
	enum class ARCTYPE : PMC_USINT
	{
		/// @brief Minor arc
		MINORARC = 0,
		/// @brief Major arc
		MAJORARC
	};

	/// @brief Arc motion mode Enum
	enum class ARCMODE : PMC_USINT
	{
		/// @brief Target + radius mode
		TARGETRADIUS = 0,
		/// @brief Center + angle mode
		CENTERANGLE
	};

	/// @brief Motion buffer options Enum
	enum class MOTIONBUFFEROPTIONS : PMC_USINT
	{
		/// @brief Block motion buffer
		BLOCKBUFFER = 0,
		/// @brief Release motion buffer
		RELEASEBUFFER,
		/// @brief Clear motion buffer
		CLEARBUFFER
	};

	/// @brief Motion macro options Enum
	enum class MOTIONMACROOPTIONS : PMC_USINT
	{
		/// @brief Clear motion macro
		CLEARMACRO = 0,
		/// @brief Finish motion macro editing
		SAVEMACRO = 2,
		/// @brief Query status of macro
		QUERYSTATUS = 4
	};

	/// @brief Group options Enum
	enum class GROUPOPTIONS : PMC_USINT
	{
		/// @brief Create group
		CREATEGROUP = 0,
		/// @brief Delete group
		DELETEGROUP,
		/// @brief Connect group
		BONDGROUP,
		/// @brief Disconnect group
		UNBONDGROUP,
		/// @brief Block motion buffer for group
		BLOCKMEMBERSBUFFER,
		/// @brief Unblock motion buffer for group
		RELEASEMEMBERSBUFFER,
		/// @brief Query group status
		QUERYSTATUS
	};

	
	/// @brief Levitation options Enum
	enum class LEVITATEOPTIONS : PMC_USINT
	{
		/// @brief Land XBOT
		LAND = 0,
		/// @brief Levitate XBOT
		LEVITATE
	};

	/// @brief Levitation speed options enum
	enum class LEVITATIONSPEED : PMC_USINT
	{
		/// @brief Levitate/Land the xbot(s) in roughly 1.6s
		APPROX_1600MS = 0,
		/// @brief Levitate/Land the xbot(s) in roughly 0.8s
		APPROX_800MS,
		/// @brief Levitate/Land the xbot(s) in roughly 0.4s
		APPROX_400MS,
		/// @brief Levitate/Land the xbot(s) in roughly 0.2s
		APPROX_200MS,
		/// @brief Levitate/Land the xbot(s) in roughly 0.1s
		APPROX_100MS,
		/// @brief Levitate/Land the xbot(s) in roughly 0.05s
		APPROX_50MS
	};

	/// @brief Mobility options enums
	enum class MOBILITYOPTIONS : PMC_USINT
	{
		/// @brief Disable XBOT
		DISABLE = 0,
		/// @brief Land XBOT
		LAND = 1,
		/// @brief Levitate XBOT
		LEVITATE = 2
	};

	/// @brief motion interrupt options Enum
	enum class MOTIONINTERRUPTOPTIONS : PMC_USINT
	{
		/// @brief Resume the xbot motion
		RESUME = 0,
		/// @brief pause the xbot motion
		PAUSE
	};

	/// @brief Async motion options Enum
	enum class ASYNCOPTIONS : PMC_USINT
	{
		/// @brief All XBOTs on flyways can be moved
		MOVEALL = 0
	};

	/// @brief Planet Motion Enum
	enum class PLANETOPTIONS : PMC_USINT
	{
		/// @brief Remove the planet XBOTs listed in this command from the sun XBOT's planet list
		REMOVEPLANETS = 0,
		/// @brief add the planet XBOTs listed in this command to the sun XBOT's planet list
		ADDPLANETS
	};

	/// @brief Mover type enumeration
	enum class MOVERTYPE : PMC_USINT
	{
		/// @brief M3-06 120mm x 120mm
		M3_06 = 0,
		/// @brief Reserved
		RESERVED1,
		/// @brief M3-08 180mm x 120mm
		M3_08,
		/// @brief M3-08 120mm x 180mm
		RESERVED3,
		/// @brief Reserved
		M3_09X,
		/// @brief Reserved
		M3_09Y,
		/// @brief M3-10 180mm x 180mm
		M3_10,
		/// @brief Reserved
		RESERVED7,
		/// @brief M3-11 210mm x 180mm
		M3_11X,
		/// @brief M3-11 180mm x 210mm
		M3_11Y,
		/// @brief Reserved
		RESERVED10,
		/// @brief Reserved
		RESERVED11,
		/// @brief M3-12 210mm x 210mm
		M3_12,
		/// @brief Reserved
		RESERVED13,
		/// @brief M3-13 240mm x 240mm
		M3_13,
		/// @brief Reserved
		RESERVED15,
		/// @brief M3-17 300mm x 300mm
		M3_17,
		/// @brief Reserved
		RESERVED17,
		/// @brief M3-18 330mm x 330mm
		M3_18,
		/// @brief Reserved
		RESERVED19,
		/// @brief Reserved
		RESERVED20,
		/// @brief Reserved
		RESERVED21
	};

	/// @brief Enum containing the index of mover properties
	enum class MOVERPROPERTY : PMC_USINT
	{
		/// @brief Mover type 
		MOVERTYPE_0 = 0,
		/// @brief Configure payload on the mover, in kg
		PAYLOADKG_1,
		/// @brief the height of the center of gravity of the payload, in meters
		CGHEIGHTM_2,
		/// @brief The max size of the payload or the mover, in the X direction, whichever is larger
		XDIMENSIONM_3,
		/// @brief Reserved for future use
		RESERVED_4,
		/// @brief The max size of the payload or the mover, in the Y direction, whichever is larger
		YDIMENSIONM_5 = 5,
		/// @brief Reserved for future use
		RESERVED2_6,
		/// @brief The maximum acceleration achievable by the mover, with the currently configured payload
		MAXACCELERATION_7 = 7
	};
	
	/// @brief Axis enum, base 1
	enum class AXISNAMES : PMC_USINT
	{
		/// @brief No axis selected
		NoAxis_0,
		/// @brief X Axis = 1
		X_1 = 1,
		/// @brief Y Axis = 2
		Y_2,
		/// @brief Z Axis = 3
		Z_3,
		/// @brief RX Axis = 4
		RX_4,
		/// @brief RY Axis = 5
		RY_5,
		/// @brief RZ Axis = 6
		RZ_6
	};

	/// @brief cam motion enum
	enum class CAMOPTIONS : PMC_USINT
	{
		/// @brief Stop cam motion
		STOP_CAM = 0,
		/// @brief Start cam motion
		START_CAM
	};

	/// @brief Group Bond Option Enum
	enum class GROUPBONDOPTIONS : PMC_USINT
	{
		/// @brief 6D bonded, but xy is decoupled from RZ
		SIXDOF_DECOUPLED = 0,
		/// @brief 6D bonded, but xy is coupled with RZ
		SIXDOF_COUPLED,
		/*
		
		/// @brief x,y,z,rz bonded, xy not coupled with rz
		
		XYZRZ_DECOUPLED,
		
		/// @brief x,y,z,rz bonded, xy coupled with rz
		
		XYZRZ_COUPLED
		*/
	};

	/// @brief short axes center mode Enum
	enum class SHORTAXESCENTERMODE : PMC_USINT
	{
		/// @brief XBOT center is used for rotation or tilt calculations
		XBOT_CENTER = 0,
		/// @brief User defines the center (x,y coordinates) that the XBOT rotates around
		USER_DEFINED_CENTER_XY,
	};

	/// @brief Zone state
	enum class ZONESTATE : PMC_USINT
	{
		/// @brief The zone has not been defined and cannot be used
		UNDEFINED = 0,
		/// @brief The zone is activated, XBots can move freely inside the zone and may move across the zone boundary
		ACTIVATED_UNFENCED = 1,
		/// @brief The zone is deactivating. Any XBots inside the zone are in the process of being deactivated
		DEACTIVATING = 2,
		/// @brief The zone is a loading / unloading zone, a user may add or remove XBots from the zone manually. The XBots inside the zone are deactivated. XBots may not move across the zone boundary
		LOADING_FENCED = 3,
		/// @brief The zone is activating. Any XBots inside the zone are in the process of being discovered / levitated
		ACTIVATING = 4,
		/// @brief The zone is activated, XBots can move freely inside the zone, but may not move across the zone boundary
		ACTIVATED_FENCED = 5,
		/// @brief The zone is in the process of being fenced. The system is attempting to create a fence that will stop XBots from crossing the zone boundary
		BUILDING_FENCE = 6,
	};

	/// @brief zone operation performed by the Zone Control command. 0 = Deactivate Zone, 1= Activate Zone
	enum class ZONEOPERATION : PMC_USINT
	{
		/// @brief Deactivate the zone, if successful, the zone is converted into a loading/unloading zone. Any XBots inside the zone will become deactivated
		DEACTIVATE_ZONE = 0,
		/// @brief Activated the zone, if successful, the zone is converted into a fenced active zone. Any XBots inside the zone will be levitated
		ACTIVATE_ZONE = 1,
	};

	
	/// @brief fence operation performed by the Zone Fence Control command. 0 = remove fence around the zone, 1= build fence around the zone
	enum class FENCEOPERATION : PMC_USINT
	{
		/// @brief remove the fence around the zone, XBots can freely move across the zone boundary
		REMOVE_FENCE = 0,
		/// @brief build the fence around the zone, XBots cannot move across the zone boundary
		BUILD_FENCE = 1,
	};

	/// @brief queue operation performed by the Queue Control Command. 0=create queue, 1=delete queue
	enum class QUEUEOPERATION : PMC_USINT
	{
		/// @brief Create a queue, queue definitions are required
		CREATE_QUEUE = 0,
		/// @brief Delete the queueing area
		DELETE_QUEUE = 1,
	};

	/// @brief select an area of the region to use
	enum class AREASELECTION : PMC_USINT
	{
		/// @brief An area located at the bottom left corner of the queue, with the same size as the largest allowable XBot inside the area
		BOTTOM_LEFT = 0,
		/// @brief An area located at the top left corner of the queue, with the same size as the largest allowable XBot inside the area
		TOP_LEFT = 1,
		/// @brief An area located at the top right corner of the queue, with the same size as the largest allowable XBot inside the area
		TOP_RIGHT = 2,
		/// @brief An area located at the bottom right corner of the queue, with the same size as the largest allowable XBot inside the area
		BOTTOM_RIGHT = 3,
	};

	/// @brief operation performed by the auto loading zone control command
	enum class ALZONEOPERATION : PMC_USINT
	{
		/// @brief Create a autoload zone
		CREATE_AUTOLOAD_ZONE = 0,
		/// @brief Delete the auto load zone
		DELETE_AUTOLOAD_ZONE = 1,
		/// @brief Activate the auto load zone
		ACTIVATE_AUTOLOAD_ZONE = 2,
		/// @brief Deactivate the auto load zone
		DEACTIVATE_AUTOLOAD_ZONE = 3
	};

	/// @brief define the auto loading zone as either loading or unloading
	enum class ALZONETYPE : PMC_USINT
	{
		/// @brief unload from flyway zone, send XBot to external device
		UNLOAD_ZONE = 0,
		/// @brief load to flyway zone, receive XBot from external device
		LOAD_ZONE = 1,
	};

	/// @brief configured auto loading zone state
	enum class ALZONESTATE : PMC_USINT
	{
		/// @brief auto loading zone has not been defined
		UNDEFINED = 0,
		/// @brief auto loading zone has been defined
		DEFINED = 1,
		/// @brief defined as auto unloading zone (removing XBot from flyway)
		UNLOADING_ZONE = 2,
		/// @brief defined as auto loading zone (adding XBot to flyway)
		LOADING_ZONE = 3,
	};

	/// @brief unloading behaviour, either non-stop unloading, or stop before unloading
	enum class ALZONEUNLOADMODE : PMC_USINT
	{
		/// @brief XBot will come to a stop at the boundary before the unload operation
		STOP_BEFORE_UNLOAD = 0,
		/// @brief XBot will not stop but smoothly transition its motion into an unload operation
		NONSTOP_UNLOAD
	};
	
	/// @brief what feedback type has been configured
	enum class FEEDBACKTYPECONFIGURED : PMC_USINT
	{		
		/// @brief no feedback has been configured
		NO_FEEDBACK = 0,		
		/// @brief standard feedback has been configured
		STANDARD_FEEDBACK,		
		/// @brief extended feedback has been configured
		EXTENDED_FEEDBACK
	};
}