#pragma once

// Constants
//TODO: Make User adjustable
// Based on ICAO/LH findings
#define PAX_WEIGHT(IS_IMPERIAL) ((IS_IMPERIAL) ? (190.0) : (86.0))
#define BAG_WEIGHT(IS_IMPERIAL) ((IS_IMPERIAL) ? (50.0) : (23.0))

// 190lbs default
#define PILOT_WEIGHT(IS_IMPERIAL) ((IS_IMPERIAL) ? (190.0) : (86.0))
// 2x 190lbs default
#define FRONT_CREW_WEIGHT(IS_IMPERIAL) ((IS_IMPERIAL) ? (380.0) : (172.0))
// 5x 190lbs default
#define REAR_CREW_WEIGHT(IS_IMPERIAL) ((IS_IMPERIAL) ? (950.0) : (430.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))
#define MAX_UPPER_CARGO(IS_IMPERIAL) ((IS_IMPERIAL) ? (6.5 * 15000.0) : (6.5 * 6804.0))
//LD3s due to 70in door
#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))

// All actual Business seats
#define MAX_BUSINESS_1 30
// First 5 rows of economy
#define MAX_BUSINESS_2 45
// Next 14 rows
#define MAX_ECONOMY_1 86
// Remaining rows
#define MAX_ECONOMY_2 137
// Total
#define MAX_PAX 298

// Max ZFW
#define MAX_PAX_ZFW(IS_IMPERIAL) ((IS_IMPERIAL) ? (400000) : (181437))
#define MAX_F_ZFW(IS_IMPERIAL) ((IS_IMPERIAL) ? (451300) : (204706))

// 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 part 1
#define ARM_EMPTY -159.6
// Pax Only
#define ARM_PILOT 984.0
#define ARM_FIRST_OFFICER 984.0
#define ARM_ENGINEER 960.0
#define ARM_PAX_CABIN_CREW_FRONT 792.0
#define ARM_PAX_BUSINESS1_LEFT 540.0
#define ARM_PAX_BUSINESS1_CENTER 540.0
#define ARM_PAX_BUSINESS1_RIGHT 540.0
#define ARM_PAX_BUSINESS2_LEFT 300.0
#define ARM_PAX_BUSINESS2_CENTER 300.0
#define ARM_PAX_BUSINESS2_RIGHT 300.0
#define ARM_PAX_ECONOMY1_LEFT -240.0
#define ARM_PAX_ECONOMY1_CENTER -240.0
#define ARM_PAX_ECONOMY1_RIGHT -240.0
#define ARM_PAX_ECONOMY2_LEFT -600.0
#define ARM_PAX_ECONOMY2_CENTER -600.0
#define ARM_PAX_ECONOMY2_RIGHT -600.0
#define ARM_PAX_CABIN_CREW_REAR -660.0
// Cargo only
#define ARM_F_UPPER1_LEFT 660
#define ARM_F_UPPER1_RIGHT 660
#define ARM_F_UPPER2_LEFT 240
#define ARM_F_UPPER2_RIGHT 240
#define ARM_F_UPPER3_LEFT -240
#define ARM_F_UPPER3_RIGHT -240
#define ARM_F_UPPER4_LEFT -600
#define ARM_F_UPPER4_RIGHT -600
// Shared part 2
#define ARM_FORWARD_CARGO 360.0
#define ARM_REAR_CARGO -360.0
#define ARM_LEFT_AUX 60.0
#define ARM_RIGHT_AUX 60.0
// 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 Stuff
// TODO: Extract following four from CFG at runtime
#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)
#define TO_PERCENT_MAC(POS) ((((POS) - LEMAC) / MAC) * -100.0)

// CG Limits
#define MIN_CG 12.0
#define MAX_CG 34.0
#define CG_TOLERANCE 0.05

// 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))

// GSX States
#define GSX_SERVICE_ACTIVE 5

// SimConnect 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,
};

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

typedef struct {
    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
} GSXData_t;

typedef struct {
    // SimConnect mapped
    double pilot;
    double firstOfficer;
    double engineer;
    double cabinCrewFront;
    double business1Left;
    double business1Center;
    double business1Right;
    double business2Left;
    double business2Center;
    double business2Right;
    double economy1Left;
    double economy1Center;
    double economy1Right;
    double economy2Left;
    double economy2Center;
    double economy2Right;
    double cabinCrewRear;
    double forwardCargo;
    double rearCargo;
    double leftAux;
    double rightAux;

    // Additional properties
    double empty;
    double total;
    double CGTarget;
    double ZFWCG;
    double TOCG;
    struct paxCount {
        unsigned char business1;
        unsigned char business2;
        unsigned char economy1;
        unsigned char economy2;
        unsigned short total;
    } paxCount;
} paxPayloadData_t;
typedef struct {
    double pilot;
    double firstOfficer;
    double engineer;
    double cabinCrewFront;
    double business1Left;
    double business1Center;
    double business1Right;
    double business2Left;
    double business2Center;
    double business2Right;
    double economy1Left;
    double economy1Center;
    double economy1Right;
    double economy2Left;
    double economy2Center;
    double economy2Right;
    double cabinCrewRear;
    double forwardCargo;
    double rearCargo;
    double leftAux;
    double rightAux;
} paxPayloadDataSet_t;

typedef struct {
    // SimConnect mapped
    double pilot;
    double firstOfficer;
    double engineer;
    double upper1Left;
    double upper1Right;
    double upper2Left;
    double upper2Right;
    double upper3Left;
    double upper3Right;
    double upper4Left;
    double upper4Right;
    double lowerForward;
    double lowerRear;
    double leftAux;
    double rightAux;

    // Additional properties
    double empty;
    double total;
    double CGTarget;
    double ZFWCG;
    double TOCG;
    struct stations {
        unsigned int upper1;
        unsigned int upper2;
        unsigned int upper3;
        unsigned int upper4;
        unsigned int total;
    } stations;
} fPayloadData_t;
typedef struct {
    // SimConnect mapped
    double pilot;
    double firstOfficer;
    double engineer;
    double upper1Left;
    double upper1Right;
    double upper2Left;
    double upper2Right;
    double upper3Left;
    double upper3Right;
    double upper4Left;
    double upper4Right;
    double lowerForward;
    double lowerRear;
    double leftAux;
    double rightAux;
} fPayloadDataSet_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;