/*****************************************************************************
 * $LastChangedDate: 2011-04-23 21:07:07 -0400 (Sat, 23 Apr 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Aircraft classes.
 *//*
 * LEGAL:   COPYRIGHT (C) 2007 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#ifndef PROGRAM_AIRCRAFT_HH
#define PROGRAM_AIRCRAFT_HH 1

#include <vector>
#include "graph/module.hh"
#include "graph/subgraph.hh"
using namespace graph;

namespace program {

enum eAircraftType
{
    // And update Lua and gui/gui.cc
    eAircraftType_Spitfire,     // 0
    eAircraftType_Corsair,      // 1
    eAircraftType_P51,          // 2
    eAircraftType_F82,          // 3
    eAircraftType_F86,          // 4
    eAircraftType_A4,           // 5
    eAircraftType_F14,          // 6
    eAircraftType_F15,          // 7
    eAircraftType_F16,          // 8
    eAircraftType_F18,          // 9
    eAircraftType_SR71,         // 10
    eAircraftType_Mirage2000,   // 11
    eAircraftType_SU37,         // 12
    eAircraftType_SpaceShuttle, // 13

    // Special aircraft that cannot be selected by user:
    eAircraftType_Sikorsky      = 100,
};

////////////////////////////////////////////////////////////////////////////////
/// @brief Spitfire (Seafire IIIC).
///
class SpitfireAircraft : public Aircraft
{
PREVENT_COPYING(SpitfireAircraft)
typedef Aircraft Parent;
public:
                    SpitfireAircraft( shptr<Graph> graph, const WorldVertex& pos );
                    ~SpitfireAircraft();
    virtual const string GetName( void ) { return string("SpitfireAircraft"); }
    CLASS_METHOD const AircraftSpecs& ClassGetSpecs( void );
    virtual      const AircraftSpecs&      GetSpecs( void );
    virtual void    SetLandingGear( const bool down );
    virtual bool    IfHasPropeller( void ) { return true; }
    virtual void    SetThrottle( const fp throttle );
    virtual void    RotateControlSurfaces( const uint axis, const fp controlFraction );

private:
    virtual void    Tick( const Milliseconds millisecElapsed );
    void            RotatePropeller( void );

private:
    shptr<Subgraph>     mSubgraphPropeller1, mSubgraphPropeller2;  // 4 blades
    shptr<Subgraph>     mSubgraphPropeller3, mSubgraphPropeller4, mSubgraphPropellerDisc;
    shptr<Subgraph>     mSubgraphGear0, mSubgraphGear1, mSubgraphGear2;
    shptr<Subgraph>     mSubgraphAileronLeft, mSubgraphAileronRight;
    shptr<Subgraph>     mSubgraphElevatorLeft, mSubgraphElevatorRight;
    shptr<Subgraph>     mSubgraphRudder;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief F4U Corsair.
///
class CorsairAircraft : public Aircraft
{
PREVENT_COPYING(CorsairAircraft)
typedef Aircraft Parent;
public:
                    CorsairAircraft( shptr<Graph> graph, const WorldVertex& pos );
                    ~CorsairAircraft();
    virtual const string GetName( void ) { return string("CorsairAircraft"); }
    CLASS_METHOD const AircraftSpecs& ClassGetSpecs( void );
    virtual      const AircraftSpecs&      GetSpecs( void );
    virtual void    SetLandingGear( const bool down );
    virtual bool    IfHasPropeller( void ) { return true; }
    virtual void    RotateControlSurfaces( const uint axis, const fp controlFraction );

private:
    virtual void    Tick( const Milliseconds millisecElapsed );
    void            RotatePropeller( void );

private:
    shptr<Subgraph>     mSubgraphPropeller0, mSubgraphPropeller1;
    shptr<Subgraph>     mSubgraphGear0,  mSubgraphGear1,  mSubgraphGear2,  mSubgraphGear3;
    shptr<Subgraph>     mSubgraphGear4,  mSubgraphGear5,  mSubgraphGear6,  mSubgraphGear7;
    shptr<Subgraph>     mSubgraphGear8,  mSubgraphGear9,  mSubgraphGear10, mSubgraphGear11;
    shptr<Subgraph>     mSubgraphGear12, mSubgraphGear13, mSubgraphGear14, mSubgraphGear15;
    shptr<Subgraph>     mSubgraphGear16, mSubgraphGear17, mSubgraphGear18, mSubgraphGear19;
    shptr<Subgraph>     mSubgraphGear20;
    shptr<Subgraph>     mSubgraphAileronLeft, mSubgraphAileronRight;
    shptr<Subgraph>     mSubgraphElevatorLeft, mSubgraphElevatorRight;
    shptr<Subgraph>     mSubgraphRudder;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief P-51D Mustang.
///
class P51Aircraft : public Aircraft
{
PREVENT_COPYING(P51Aircraft)
typedef Aircraft Parent;
public:
                    P51Aircraft( shptr<Graph> graph, const WorldVertex& pos );
                    ~P51Aircraft();
    virtual const string GetName( void ) { return string("P51Aircraft"); }
    CLASS_METHOD const AircraftSpecs& ClassGetSpecs( void );
    virtual      const AircraftSpecs&      GetSpecs( void );
    virtual void    SetLandingGear( const bool down );
    virtual bool    IfHasPropeller( void ) { return true; }
    virtual void    RotateControlSurfaces( const uint axis, const fp controlFraction );

private:
    virtual void    Tick( const Milliseconds millisecElapsed );
    void            RotatePropeller( void );

private:
    shptr<Subgraph>     mSubgraphPropeller1;    ///< this particular P-51 model
    shptr<Subgraph>     mSubgraphPropeller2;    ///< has two nodes for a 4 bladed propeller
    //
    shptr<Subgraph>     mSubgraphLeftGearWheel;
    shptr<Subgraph>     mSubgraphLeftGearStrut;
    shptr<Subgraph>     mSubgraphLeftInnerGearCover;
    shptr<Subgraph>     mSubgraphLeftOuterGearCover;
    shptr<Subgraph>     mSubgraphLeftTailGearDoor;
    //
    shptr<Subgraph>     mSubgraphRightGearWheel;
    shptr<Subgraph>     mSubgraphRightGearStrut;
    shptr<Subgraph>     mSubgraphRightInnerGearCover;
    shptr<Subgraph>     mSubgraphRightOuterGearCover;
    shptr<Subgraph>     mSubgraphRightTailGearDoor;
    //
    shptr<Subgraph>     mSubgraphTailGearWheel;
    shptr<Subgraph>     mSubgraphTailGearStrut;
    //
    shptr<Subgraph>     mSubgraphAileronLeft, mSubgraphAileronRight;
    shptr<Subgraph>     mSubgraphElevatorLeft, mSubgraphElevatorRight, mSubgraphRudder;
    //
    shptr<Subgraph>     mSubgraphJunk0, mSubgraphJunk1;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief F-82 Twin Mustang.
///
class F82Aircraft : public Aircraft
{
PREVENT_COPYING(F82Aircraft)
typedef Aircraft Parent;
public:
                    F82Aircraft( shptr<Graph> graph, const WorldVertex& pos );
                    ~F82Aircraft();
    virtual const string GetName( void ) { return string("F82Aircraft"); }
    CLASS_METHOD const AircraftSpecs& ClassGetSpecs( void );
    virtual      const AircraftSpecs&      GetSpecs( void );
    virtual void    SetLandingGear( const bool down );
    virtual bool    IfHasPropeller( void ) { return true; }
    virtual void    RotateControlSurfaces( const uint axis, const fp controlFraction );

private:
    virtual void    Tick( const Milliseconds millisecElapsed );
    void            RotatePropeller( void );
    void            TranslatePropeller( const fp dir );  // (F82-specific)

private:
    shptr<Subgraph>     mSubgraphPropeller1;  // each propeller of the Twin Mustang
    shptr<Subgraph>     mSubgraphPropeller2;  // has 2 subgraphs
    shptr<Subgraph>     mSubgraphPropeller3;
    shptr<Subgraph>     mSubgraphPropeller4;
    //
    shptr<Subgraph>     mSubgraphLeftGearWheel;
    shptr<Subgraph>     mSubgraphLeftGearStrut;
    shptr<Subgraph>     mSubgraphLeftInnerGearCover;
    shptr<Subgraph>     mSubgraphLeftInnerGearCover2;
    shptr<Subgraph>     mSubgraphLeftOuterGearCover;
    shptr<Subgraph>     mSubgraphLeftTailGearDoor;
    //
    shptr<Subgraph>     mSubgraphRightGearWheel;
    shptr<Subgraph>     mSubgraphRightGearStrut;
    shptr<Subgraph>     mSubgraphRightInnerGearCover;
    shptr<Subgraph>     mSubgraphRightInnerGearCover2;
    shptr<Subgraph>     mSubgraphRightOuterGearCover;
    shptr<Subgraph>     mSubgraphRightTailGearDoor;
    //
    shptr<Subgraph>     mSubgraphTailGearWheel;
    shptr<Subgraph>     mSubgraphTailGearStrut;
    shptr<Subgraph>     mSubgraphTailGearWheel2;
    shptr<Subgraph>     mSubgraphTailGearStrut2;
    //
    shptr<Subgraph>     mSubgraphAileronLeft, mSubgraphAileronRight;
    shptr<Subgraph>     mSubgraphElevator;
    shptr<Subgraph>     mSubgraphRudderLeft, mSubgraphRudderRight;
    //
    shptr<Subgraph>     mSubgraphJunk0, mSubgraphJunk1;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief F-86 Sabre.
///
class F86Aircraft : public Aircraft
{
PREVENT_COPYING(F86Aircraft)
typedef Aircraft Parent;
public:
                    F86Aircraft( shptr<Graph> graph, const WorldVertex& pos );
                    ~F86Aircraft();
    virtual const string GetName( void ) { return string("F86Aircraft"); }
    CLASS_METHOD const AircraftSpecs& ClassGetSpecs( void );
    virtual      const AircraftSpecs&      GetSpecs( void );
    virtual void    SetLandingGear( const bool down );
    virtual bool    IfHasPropeller( void ) { return false; }
    virtual void    RotateControlSurfaces( const uint axis, const fp controlFraction );

private:
    shptr<Subgraph>     mSubgraphGear0, mSubgraphGear1, mSubgraphGear2;
    shptr<Subgraph>     mSubgraphGear3, mSubgraphGear4, mSubgraphGear5;
    //
    shptr<Subgraph>     mSubgraphAileronLeft, mSubgraphAileronRight;
    shptr<Subgraph>     mSubgraphElevatorLeft, mSubgraphElevatorRight;
    shptr<Subgraph>     mSubgraphRudder;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief A-4 Skyhawk.
///
class A4Aircraft : public Aircraft
{
PREVENT_COPYING(A4Aircraft)
typedef Aircraft Parent;
public:
                    A4Aircraft( shptr<Graph> graph, const WorldVertex& pos );
                    ~A4Aircraft();
    virtual const string GetName( void ) { return string("A4Aircraft"); }
    CLASS_METHOD const AircraftSpecs& ClassGetSpecs( void );
    virtual      const AircraftSpecs&      GetSpecs( void );
    virtual void    SetLandingGear( const bool down );
    virtual bool    IfHasPropeller( void ) { return false; }
    virtual void    RotateControlSurfaces( const uint axis, const fp controlFraction );

private:
    shptr<Subgraph>     mSubgraphGear0, mSubgraphGear1, mSubgraphGear2;
    shptr<Subgraph>     mSubgraphGear3, mSubgraphGear4, mSubgraphGear5;
    shptr<Subgraph>     mSubgraphGear6, mSubgraphGear7, mSubgraphGear8;
    shptr<Subgraph>     mSubgraphGear9, mSubgraphGear10, mSubgraphGear11;
    shptr<Subgraph>     mSubgraphGear12, mSubgraphGear13, mSubgraphGear14;
    shptr<Subgraph>     mSubgraphGear15, mSubgraphGear16, mSubgraphGear17;
    shptr<Subgraph>     mSubgraphAileronLeft, mSubgraphAileronRight;
    shptr<Subgraph>     mSubgraphAileronLeft2, mSubgraphAileronRight2;
    shptr<Subgraph>     mSubgraphElevatorLeft, mSubgraphElevatorRight;
    shptr<Subgraph>     mSubgraphRudder;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief F-14 Tomcat.
///
class F14Aircraft : public Aircraft
{
PREVENT_COPYING(F14Aircraft)
typedef Aircraft Parent;
public:
                    F14Aircraft( shptr<Graph> graph, const WorldVertex& pos );
                    ~F14Aircraft();
    virtual void    Reset( void );
    virtual const string GetName( void ) { return string("F14Aircraft"); }
    CLASS_METHOD const AircraftSpecs& ClassGetSpecs( void );
    virtual      const AircraftSpecs&      GetSpecs( void );
    virtual void    SetLandingGear( const bool down );
    virtual bool    IfHasPropeller( void ) { return false; }
    virtual void    SetThrottle( const fp throttle );
    virtual void    SwingWings( const float fraction );
    virtual void    RotateControlSurfaces( const uint axis, const fp controlFraction );

private:
    shptr<Subgraph>     mSubgraphGear0, mSubgraphGear1, mSubgraphGear2;
    shptr<Subgraph>     mSubgraphGear3, mSubgraphGear4, mSubgraphGear5;
    shptr<Subgraph>     mSubgraphGear6, mSubgraphGear7, mSubgraphGear8;
    shptr<Subgraph>     mSubgraphGear9, mSubgraphGear10, mSubgraphGear11;
    shptr<Subgraph>     mSubgraphGear12, mSubgraphGear13, mSubgraphGear14;
    shptr<Subgraph>     mSubgraphGear15, mSubgraphGear16, mSubgraphGear17;
    shptr<Subgraph>     mSubgraphGear18, mSubgraphGear19, mSubgraphGear20;
    shptr<Subgraph>     mSubgraphGear21, mSubgraphGear22, mSubgraphGear23;
    shptr<Subgraph>     mSubgraphGear24, mSubgraphGear25, mSubgraphGear26;
    shptr<Subgraph>     mSubgraphGear27, mSubgraphGear28, mSubgraphGear29;
    shptr<Subgraph>     mSubgraphGear30, mSubgraphGear31, mSubgraphGear32;
    shptr<Subgraph>     mSubgraphGear33, mSubgraphGear34;
    shptr<Subgraph>     mSubgraphWingLeft0, mSubgraphWingLeft1, mSubgraphWingLeft2, mSubgraphWingLeft3;
    shptr<Subgraph>     mSubgraphWingLeft4, mSubgraphWingLeft5, mSubgraphWingLeft6, mSubgraphWingLeft7;
    shptr<Subgraph>     mSubgraphWingLeft8, mSubgraphWingLeft9, mSubgraphWingLeft10, mSubgraphWingLeft11;
    shptr<Subgraph>     mSubgraphWingLeft12, mSubgraphWingLeft13, mSubgraphWingLeft14, mSubgraphWingLeft15;
    shptr<Subgraph>     mSubgraphWingLeft16, mSubgraphWingLeft17, mSubgraphWingLeft18, mSubgraphWingLeft19;
    shptr<Subgraph>     mSubgraphWingLeft20, mSubgraphWingLeft21, mSubgraphWingLeft22, mSubgraphWingLeft23;
    shptr<Subgraph>     mSubgraphWingLeft24, mSubgraphWingLeft25, mSubgraphWingLeft26, mSubgraphWingLeft27;
    shptr<Subgraph>     mSubgraphWingLeft28, mSubgraphWingLeft29;
    shptr<Subgraph>     mSubgraphWingRight0, mSubgraphWingRight1, mSubgraphWingRight2, mSubgraphWingRight3;
    shptr<Subgraph>     mSubgraphWingRight4, mSubgraphWingRight5, mSubgraphWingRight6, mSubgraphWingRight7;
    shptr<Subgraph>     mSubgraphWingRight8, mSubgraphWingRight9, mSubgraphWingRight10, mSubgraphWingRight11;
    shptr<Subgraph>     mSubgraphWingRight12, mSubgraphWingRight13, mSubgraphWingRight14, mSubgraphWingRight15;
    shptr<Subgraph>     mSubgraphWingRight16, mSubgraphWingRight17, mSubgraphWingRight18, mSubgraphWingRight19;
    shptr<Subgraph>     mSubgraphWingRight20, mSubgraphWingRight21, mSubgraphWingRight22, mSubgraphWingRight23;
    shptr<Subgraph>     mSubgraphWingRight24, mSubgraphWingRight25, mSubgraphWingRight26, mSubgraphWingRight27;
    shptr<Subgraph>     mSubgraphWingRight28, mSubgraphWingRight29;
    shptr<Subgraph>     mSubgraphTaileronLeft, mSubgraphTaileronRight, mSubgraphRudderLeft, mSubgraphRudderRight;
    shptr<Subgraph>     mSubgraphLadder0, mSubgraphLadder1, mSubgraphLadder2, mSubgraphRefuelProbe;
    shptr<Subgraph>     mSubgraphFlameInner0, mSubgraphFlameInner1, mSubgraphFlameOuter0, mSubgraphFlameOuter1;
    shptr<Subgraph>     mSubgraphShockWave, mSubgraphManeuverVortexLeft, mSubgraphManeuverVortexRight;
    std::vector<shptr<Subgraph> > mGearSubgraphs, mLeftWingSubgraphs, mRightWingSubgraphs;
    fp                  mSwingWingsFraction;
    fp                  mAileronFraction;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief F-15 Eagle.
///
class F15Aircraft : public Aircraft
{
PREVENT_COPYING(F15Aircraft)
typedef Aircraft Parent;
public:
                    F15Aircraft( shptr<Graph> graph, const WorldVertex& pos );
                    ~F15Aircraft();
    virtual const string GetName( void ) { return string("F15Aircraft"); }
    CLASS_METHOD const AircraftSpecs& ClassGetSpecs( void );
    virtual      const AircraftSpecs&      GetSpecs( void );
    virtual void    SetLandingGear( const bool down );
    virtual bool    IfHasPropeller( void ) { return false; }
    virtual void    SetThrottle( const fp throttle );
    virtual void    RotateControlSurfaces( const uint axis, const fp controlFraction );

private:
    shptr<Subgraph>     mSubgraphGear0, mSubgraphGear1, mSubgraphGear2;
    shptr<Subgraph>     mSubgraphGear3, mSubgraphGear4, mSubgraphGear5;
    shptr<Subgraph>     mSubgraphFlame0, mSubgraphFlame1;
    shptr<Subgraph>     mSubgraphAileronLeft, mSubgraphAileronRight;
    shptr<Subgraph>     mSubgraphElevatorLeft, mSubgraphElevatorRight;
    shptr<Subgraph>     mSubgraphRudderLeft, mSubgraphRudderRight;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief F-16 Falcon.
///
class F16Aircraft : public Aircraft
{
PREVENT_COPYING(F16Aircraft)
typedef Aircraft Parent;
public:
                    F16Aircraft( shptr<Graph> graph, const WorldVertex& pos );
                    ~F16Aircraft();
    virtual const string GetName( void ) { return string("F16Aircraft"); }
    CLASS_METHOD const AircraftSpecs& ClassGetSpecs( void );
    virtual      const AircraftSpecs&      GetSpecs( void );
    virtual void    SetLandingGear( const bool down );
    virtual bool    IfHasPropeller( void ) { return false; }
    virtual void    SetThrottle( const fp throttle );
    virtual void    RotateControlSurfaces( const uint axis, const fp controlFraction );

private:
    shptr<Subgraph>     mSubgraphGear0,  mSubgraphGear1,  mSubgraphGear2;
    shptr<Subgraph>     mSubgraphGear3,  mSubgraphGear4,  mSubgraphGear5;
    shptr<Subgraph>     mSubgraphGear6,  mSubgraphGear7,  mSubgraphGear8;
    shptr<Subgraph>     mSubgraphGear9,  mSubgraphGear10, mSubgraphGear11;
    shptr<Subgraph>     mSubgraphGear12, mSubgraphGear13, mSubgraphGear14;
    shptr<Subgraph>     mSubgraphGear15, mSubgraphGear16, mSubgraphGear17;
    shptr<Subgraph>     mSubgraphFlame0, mSubgraphFlame1;
    shptr<Subgraph>     mSubgraphAileronLeft, mSubgraphAileronRight;
    shptr<Subgraph>     mSubgraphFlapLeft, mSubgraphFlapRight;
    shptr<Subgraph>     mSubgraphElevatorLeft, mSubgraphElevatorRight;
    shptr<Subgraph>     mSubgraphRudder0, mSubgraphRudder1, mSubgraphRudder2, mSubgraphRudder3;
    shptr<Subgraph>     mSubgraphJunk0, mSubgraphJunk1;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief F-18 Hornet.
///
class F18Aircraft : public Aircraft
{
PREVENT_COPYING(F18Aircraft)
typedef Aircraft Parent;
public:
                    F18Aircraft( shptr<Graph> graph, const WorldVertex& pos );
                    ~F18Aircraft();
    virtual const string GetName( void ) { return string("F18Aircraft"); }
    CLASS_METHOD const AircraftSpecs& ClassGetSpecs( void );
    virtual      const AircraftSpecs&      GetSpecs( void );
    virtual void    SetLandingGear( const bool down );
    virtual bool    IfHasPropeller( void ) { return false; }
    virtual void    SetThrottle( const fp throttle );
    virtual void    RotateControlSurfaces( const uint axis, const fp controlFraction );

private:
    shptr<Subgraph>     mSubgraphGear0, mSubgraphGear1, mSubgraphGear2;
    shptr<Subgraph>     mSubgraphGear3, mSubgraphGear4, mSubgraphGear5;
    shptr<Subgraph>     mSubgraphFlame0, mSubgraphFlame1;
    shptr<Subgraph>     mSubgraphAileronLeft, mSubgraphAileronRight;
    shptr<Subgraph>     mSubgraphElevatorLeft, mSubgraphElevatorRight;
    shptr<Subgraph>     mSubgraphRudderLeft, mSubgraphRudderRight;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief SR-71 Blackbird.
///
class SR71Aircraft : public Aircraft
{
PREVENT_COPYING(SR71Aircraft)
typedef Aircraft Parent;
public:
                    SR71Aircraft( shptr<Graph> graph, const WorldVertex& pos );
                    ~SR71Aircraft();
    virtual const string GetName( void ) { return string("SR71Aircraft"); }
    CLASS_METHOD const AircraftSpecs& ClassGetSpecs( void );
    virtual      const AircraftSpecs&      GetSpecs( void );
    virtual void    SetLandingGear( const bool down );
    virtual bool    IfHasPropeller( void ) { return false; }
    virtual bool    IfHasGuns( void ) { return false; }
    virtual void    SetThrottle( const fp throttle );
    virtual void    RotateControlSurfaces( const uint axis, const fp controlFraction );

private:
    shptr<Subgraph>     mSubgraphGear0, mSubgraphGear1, mSubgraphGear2;
    shptr<Subgraph>     mSubgraphStrut0,  mSubgraphStrut1,  mSubgraphStrut2,  mSubgraphStrut3;
    shptr<Subgraph>     mSubgraphStrut4,  mSubgraphStrut5,  mSubgraphStrut6,  mSubgraphStrut7;
    shptr<Subgraph>     mSubgraphStrut8,  mSubgraphStrut9,  mSubgraphStrut10, mSubgraphStrut11;
    shptr<Subgraph>     mSubgraphStrut12, mSubgraphStrut13, mSubgraphStrut14, mSubgraphStrut15;
    shptr<Subgraph>     mSubgraphParachute;
    shptr<Subgraph>     mSubgraphFlame0, mSubgraphFlame1, mSubgraphFlame2;
    shptr<Subgraph>     mSubgraphFlame3, mSubgraphFlame4, mSubgraphFlame5;
    shptr<Subgraph>     mSubgraphAileronLeft, mSubgraphAileronRight;
    shptr<Subgraph>     mSubgraphElevatorLeft, mSubgraphElevatorRight;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief Mirage 2000.
///
class Mirage2000Aircraft : public Aircraft
{
PREVENT_COPYING(Mirage2000Aircraft)
typedef Aircraft Parent;
public:
                    Mirage2000Aircraft( shptr<Graph> graph, const WorldVertex& pos );
                    ~Mirage2000Aircraft();
    virtual const string GetName( void ) { return string("Mirage2000Aircraft"); }
    CLASS_METHOD const AircraftSpecs& ClassGetSpecs( void );
    virtual      const AircraftSpecs&      GetSpecs( void );
    virtual void    SetLandingGear( const bool down );
    virtual bool    IfHasPropeller( void ) { return false; }
    virtual void    SetThrottle( const fp throttle );
    virtual void    RotateControlSurfaces( const uint axis, const fp controlFraction );

private:
    shptr<Subgraph>     mSubgraphGear0, mSubgraphGear1, mSubgraphGear2;
    shptr<Subgraph>     mSubgraphGear3, mSubgraphGear4, mSubgraphGear5;
    shptr<Subgraph>     mSubgraphGear6, mSubgraphGear7, mSubgraphGear8;
    shptr<Subgraph>     mSubgraphFlame0, mSubgraphFlame1;
    shptr<Subgraph>     mSubgraphAileronLeft, mSubgraphAileronRight;  // are elevators also
    shptr<Subgraph>     mSubgraphRudder;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief SU-37 Flanker.
///
class SU37Aircraft : public Aircraft
{
PREVENT_COPYING(SU37Aircraft)
typedef Aircraft Parent;
public:
                    SU37Aircraft( shptr<Graph> graph, const WorldVertex& pos );
                    ~SU37Aircraft();
    virtual const string GetName( void ) { return string("SU37Aircraft"); }
    CLASS_METHOD const AircraftSpecs& ClassGetSpecs( void );
    virtual      const AircraftSpecs&      GetSpecs( void );
    virtual void    SetLandingGear( const bool down );
    virtual bool    IfHasPropeller( void ) { return false; }
    virtual void    SetThrottle( const fp throttle );
    virtual void    RotateControlSurfaces( const uint axis, const fp controlFraction );

private:
    shptr<Subgraph>     mSubgraphGear0;
    shptr<Subgraph>     mSubgraphFlame0, mSubgraphFlame1;
    shptr<Subgraph>     mSubgraphAileronLeft, mSubgraphAileronRight;
    shptr<Subgraph>     mSubgraphElevatorLeft, mSubgraphElevatorRight;
    shptr<Subgraph>     mSubgraphRudderLeft, mSubgraphRudderRight;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief Space Shuttle.
///
class SpaceShuttleAircraft : public Aircraft
{
PREVENT_COPYING(SpaceShuttleAircraft)
typedef Aircraft Parent;
public:
                    SpaceShuttleAircraft( shptr<Graph> graph, const WorldVertex& pos );
                    ~SpaceShuttleAircraft();
    virtual void    Reset( void );
    virtual const string GetName( void ) { return string("SpaceShuttleAircraft"); }
    CLASS_METHOD const AircraftSpecs& ClassGetSpecs( void );
    virtual      const AircraftSpecs&      GetSpecs( void );
    virtual bool    IfLandingGear( void ) { return false; }
    virtual bool    IfHasPropeller( void ) { return false; }
    virtual void    SwingWings( const float fraction );  // really open bay doors
    virtual void    SwingBayDoors( const float fraction );

private:
    shptr<Subgraph>     mSubgraphBayDoorLeft, mSubgraphBayDoorRight;
    fp                  mBayDoorsFraction;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief Sikorsky-76 rescue helicopter.
///
class SikorskyAircraft : public Aircraft
{
PREVENT_COPYING(SikorskyAircraft)
typedef Aircraft Parent;
public:
                    SikorskyAircraft( shptr<Graph> graph, const WorldVertex& pos );
                    ~SikorskyAircraft();
    virtual const string GetName( void ) { return string("SikorskyAircraft"); }
    CLASS_METHOD const AircraftSpecs& ClassGetSpecs( void );
    virtual      const AircraftSpecs&      GetSpecs( void );
    virtual void    SetLandingGear( const bool down );
    virtual bool    IfLandingGear( void ) { return false; }
    virtual bool    IfHasPropeller( void ) { return false; }

private:
    virtual void    Tick( const Milliseconds millisecElapsed );
    void            RotateRotors( void );

private:
    shptr<Subgraph>     mSubgraphRotor0, mSubgraphRotor1, mSubgraphRotor2, mSubgraphRotor3;
    shptr<Subgraph>     mSubgraphRotor4, mSubgraphRotor5, mSubgraphRotor6, mSubgraphRotor7;
    shptr<Subgraph>     mSubgraphTailRotor;
};

shptr<Aircraft>
MakeAircraft( eAircraftType aircraftType, const WorldVertex& pos, const bool loadCopy );

} // namespace program

#endif // PROGRAM_AIRCRAFT_HH
