////////////////////////////////////////////////////////////////////////////////
// QuadMech.h
// QuadMech implementation
// Copyright Bjoern Ganster
// Developed since 2007
////////////////////////////////////////////////////////////////////////////////

// Quad Mechs are also referred to as four-legged Mechs in the BattleTech
// Master Rules, where they are described in Special Case Rules, 
// p. 75 (v1), p. 82 (v2)

#ifndef QuadMech__h
#define QuadMech__h

#include "BipedMech.h"
#include "Vehicles.h"

////////////////////////////////////////////////////////////////////////////////
// State for a quad mech

class QuadMech FINAL: public Vehicle
{
public:
   // Constructor
   QuadMech();

   // Destructor
   ~QuadMech() OVERRIDE;

   //bool loadFromXml (XMLTreeConstIterator& iter, const PathChar* path) OVERRIDE;

   // Load mech limb
   //void loadPart (XMLTreeConstIterator& iter, int partNumber, 
   //    const PathChar* path);

   // Query/set data
   virtual int getInteger (int info) const;
   virtual bool setInteger (int info, int newVal);

   virtual double getWeight () const;

   virtual double calcInternalStructureWeight() const;
   double calcJJWeight ();
   virtual bool setArmor(int section, DWORD newVal, int ArmorType);
   virtual DWORD getArmor(int section, int ArmorType) const;
   virtual DWORD getInternalStructure(int section) const
   { return mInternalStructure[section]; }
   virtual int countArmorPoints() const;

   // Add weapon
   virtual bool addWeapon(int currSection, WeaponType weaponNo);

   // Remove weapon - returns number of criticals removed
   virtual int removeWeapon(int currSection, int critNo, WeaponType weaponNo, 
                            int CritCount = -1);

	// Check - and try to correct - config problems 
	// Returns true on success, false otherwise, and sets an error description on failure
	bool check(BGCPString& errors) OVERRIDE;

	// Set current animation matrices
	//void setMatrices () OVERRIDE;

	virtual void setInternalStructure (int section, DWORD newVal);

	// Set current animation matrices
	void setMatrices(double speed, DWORD missionTime) OVERRIDE;

	void setAim(double turn, double tilt) OVERRIDE;

	// Add anim parameters
	double animate(int part, double phase, double speed, double phaseShift);
	void addAnim (XMLTreeConstIterator& iter);

	// Get maximum speed in meters per second currently supported by the vehicle
	double getMaxSpeed() const OVERRIDE;

	// Check if this vehicle differentiates between front and armor for a section
	bool separateFrontAndRearArmor(int section) const OVERRIDE;

	// Check for items that the user may not add
	bool userMayAddDirectly(int section, WeaponType weaponNo) OVERRIDE;

	// Check if a critical may be removed by the user
	bool userMayRemoveDirectly (WeaponType weaponNo) OVERRIDE;

	// Show or hide the vehicle's windshiled (cockpit view may require it to be hidden)
	void windshieldVisible(bool newVal) OVERRIDE;

	// Return the number of the part corresponding to a section
	// used by updateLoadoutGeometry() to find the mesh corresponding to the mech section
	int section2part(int section, bool allowLowerArms) OVERRIDE;

	// Return the section corresponding to a limb
	int limb2section(int limb) OVERRIDE;

	// Get max armor allowed for a section
	int getMaxArmor(int section) OVERRIDE;

	// Get mesh used for the cockpit
	Mesh* getCockpitMesh() OVERRIDE;

	// Check for a collision with a polygon and handle it
	void checkCollision(const MeshPolygon* poly, Point3D& movement) OVERRIDE;

	// Based on the vehicle, connect the vehicle to a suitable AI
	AbstractVehicleAI* createAI(bool isPlayer, int environment);

	// Calculate heat for next frame
	void calcNextFrameHeat(DWORD now, double deltaT);

	// Get current heat value for this Mech
	double getHeat() const NOEXCEPT OVERRIDE;

	// Calculate movement for next frame
	void calcNextFrameMovement(double deltaT, RenderableObject* scene, DWORD now, double gravity) OVERRIDE;

	// Function to notify vehicle that it is taking damage
	void receiveDamage(RenderableObject* limb, double damage, GameObject* sender, const Point3D& pointOfImpact) OVERRIDE;

	// Mark all criticals in one section as destroyed and check for additional effects
	void destroyLimb(int section);

	// Check for for critical damage, e.g. if a weapon is destroyed by a critical hit
	void checkCriticalDamage(int section, int criticalToDestroy);

	// Query damage to armor and internal structure
	double getArmorDamage(int section, int type) const OVERRIDE;
	double getInternalDamage(int section) const OVERRIDE;

	// Check if the vehicle's cockpit has a reticle that moves horizontally
	bool reticleMovesHorizontally() const OVERRIDE;

	// The point to attack may differ per vehicle class, the center of the volume isn't necessarily a good spot to attack
	Point3D getAttackSpot(bool onGround) const OVERRIDE;

private:
	double mTorsoTilt, mTorsoTwist, mSeed;
	double realWeight;
	std::vector <MechAnimation> allAnimations;
	double torsoTwistLimit;
	double torsoTiltLimit;
	static const int Quad_Mech_Sections = 8;

	// Armor and internal structure
	int mFrontArmor[Quad_Mech_Sections];
	int mRearArmor[Quad_Mech_Sections];
	int mInternalStructure[Quad_Mech_Sections];

	std::vector <double> mArmorDamageFront, mArmorDamageRear, mInternalDamage;
	std::vector <std::vector <bool>> mCriticalDamaged;

	int checkAndFixEngineCrits(int section);

	virtual double calcRealWeight();

	// Check if a section may mount jump jets
	bool mayMountJJs (int section) OVERRIDE;

	// Current heat
	double mCurrentHeat;

	void readSpecialAttributesFromRoot(XMLTreeConstIterator& iter);
	void readSpecialAttributes(XMLTreeConstIterator& iter, const std::vector<RenderableObject*>& geometries, const PathChar* mechDir);

	void checkCritsInSection(WeaponType equipmentType, int countNeeded, int section);
};

#endif