#pragma once

#ifndef __INTELLISENSE__
#	define MODULE_EXPORT __attribute__( ( visibility( "default" ) ) )
#	define MODULE_WASM_MODNAME(mod) __attribute__((import_module(mod)))
#else
#	define MODULE_EXPORT
#	define MODULE_WASM_MODNAME(mod)
#	define __attribute__(x)
#	define __restrict__
#endif

/******************************** Constants ********************************/
// 190lbs default
#define PILOT_WEIGHT(IS_IMPERIAL) ((IS_IMPERIAL) ? (190.0) : (86.0))
// 200lbs per tank (one LD3)
#define AUX_WEIGHT(IS_IMPERIAL) ((IS_IMPERIAL) ? (200.0) : (91.0))
//PMC pallet due to 104in door
#define MAX_FRONT_CARGO(IS_IMPERIAL) ((IS_IMPERIAL) ? (6.0 * 15000.0) : (6.0 * 6804.0))
//LD3s due to 70in door, ER option takes up two slots
#define MAX_REAR_CARGO(IS_IMPERIAL, IS_ER) ((IS_IMPERIAL) ? ((IS_ER ? 12.0 : 14.0) * 3500.0) : ((IS_ER ? 12.0 : 14.0) * 1588.0))
// Max TOW
#define MAX_TOW(IS_IMPERIAL) ((IS_IMPERIAL) ? (625500) : (283722))
#define MAX_TOW_ER(IS_IMPERIAL) ((IS_IMPERIAL) ? (630500) : (285990))
// Max Fuel
#define MAX_FUEL(IS_IMPERIAL) ((IS_IMPERIAL) ? (256207) : (116213))
#define MAX_FUEL_ER(IS_IMPERIAL) ((IS_IMPERIAL) ? (282619) : (128193))
// Arms Shared
#define ARM_EMPTY -159.6
#define ARM_PILOT 984.0
#define ARM_FIRST_OFFICER 984.0
#define ARM_ENGINEER 960.0
#define ARM_FORWARD_CARGO 360.0
#define ARM_REAR_CARGO -360.0
#define ARM_LEFT_AUX 60.0
#define ARM_RIGHT_AUX 60.0
// Arms Fuel
#define ARM_MAIN1 -240.0
#define ARM_MAIN3 -240.0
#define ARM_MAIN2 120.0
#define ARM_UPPER_AUX 0.0
#define ARM_LOWER_AUX 0.0
#define ARM_MAIN1_TIP -468.0
#define ARM_MAIN3_TIP -468.0
#define ARM_TAIL -840.0
#define ARM_FORWARD_AUX1 60.0
#define ARM_FORWARD_AUX2 60.0
// MAC
#define ROOT_CHORD 34.68
#define WING_SPAN 170.5
#define WING_AREA 3648.0
#define QUARTER_MAC -165.0 //aero_center
#define TIP_CHORD ((2.0 * WING_AREA) / WING_SPAN - ROOT_CHORD)
#define TAPER_RATIO (TIP_CHORD / ROOT_CHORD)
#define MAC ((2.0 / 3.0) * ROOT_CHORD * ((1.0 + TAPER_RATIO + (TAPER_RATIO * TAPER_RATIO)) / (1.0 + TAPER_RATIO)) * 12.0)
#define LEMAC (QUARTER_MAC + (1.0 / 4.0) * MAC)
// CG Limits
#define MIN_CG 12.0
#define MAX_CG 34.0
#define CG_TOLERANCE 0.05
// GSX States
#define GSX_SERVICE_ACTIVE 5
#define GSX_SERVICE_FINISHED 6

/********************************* Macros **********************************/
// Conversions
#define TO_POUNDS(IS_IMPERIAL, VALUE) ((IS_IMPERIAL) ? (VALUE) : (VALUE) * 2.20462262185)
#define FROM_POUNDS(IS_IMPERIAL, VALUE) ((IS_IMPERIAL) ? (VALUE) : (VALUE) * (1.0 / 2.20462262185))
// MAC
#define TO_PERCENT_MAC(POS) ((((POS) - LEMAC) / MAC) * -100.0)

/********************************** ENUMS **********************************/
enum DATA_DEFINITIONS {
    DATA_DEFINITION_EMPTY_WEIGHT,
    DATA_DEFINITION_PAYLOAD_PAX,
    DATA_DEFINITION_PAYLOAD_F,
    DATA_DEFINITION_FUEL,
    DATA_DEFINITION_GSX,
    DATA_DEFINITION_USER_DATA,
};

enum DATA_REQUESTS {
    DATA_REQUEST_EMPTY_WEIGHT,
    DATA_REQUEST_PAYLOAD_PAX,
    DATA_REQUEST_PAYLOAD_F,
    DATA_REQUEST_FUEL,
    DATA_REQUEST_GSX,
    DATA_REQUEST_USER_DATA,
};

enum LOADING_STATES {
    LOADING_STATE_IDLE,
    LOADING_STATE_BOARDING,
    LOADING_STATE_BOARDED,
    LOADING_STATE_DEBOARDING,
    LOADING_STATE_DEBOARDED,
};

enum CALL_MODES {
    CALL_MODE_SB_SET,
    CALL_MODE_ZFW_SET,
    CALL_MODE_STATION_SET,
    CALL_MODE_LOAD_SET,
    CALL_MODE_UNLOAD_SET,
    CALL_MODE_OPTIONS_SET,
    CALL_MODE_GSX_RESET,
};

/***************************** Data structures *****************************/
typedef struct {
    double isCargo;
    double isER;
    double isImperial;
} UserData_t;

typedef struct {
    // SimConnect mapped
    double couatlStarted; // boolean
    double boardingState; // See manual, 5 => active
    double deboardingState; // See manual, 5 => active
    double passengersBoarded; // Num pax
    double passengersDeboarded; // Num pax
    double cargoBoarded; // In percent
    double cargoDeboarded; // In percent

    // Additional properties
    enum LOADING_STATES loadingState;
} GSXData_t;

typedef struct {
    // SimConnect mapped
    double poundsPerGallon; // DO NOT USE
    double main1;
    double main3;
    double main2;
    double upperAux;
    double lowerAux;
    double main1Tip;
    double main3Tip;
    double tail;
    double forwardAux1;
    double forwardAux2;

    // Additional properties
    double total;
} FuelData_t;

typedef struct {
    bool GSXSync;
    double paxWeightKG;
    double bagWeightKG;
    double paxWeightLBS;
    double bagWeightLBS;
} UserOptions_t;