#pragma once

#include "MW4Headers.hpp"
#include "MechLabHeaders.h"
#include "ShellScriptHeaders.hpp"
#include "ScriptErrorHeader.hpp"

namespace ElementRenderer
{
	class CameraElement;
	class GroupElement;
}

namespace MechWarrior4
{
	class Mech;
	class Weapon;
}

class SubsystemResource :
	public Plug
{
public:

	SubsystemResource(const Adept::ResourceID& data_list, const Adept::ResourceID& model_id, int type) :
	  Plug(Plug::DefaultData),
	  m_dataListID(data_list),
	  m_modelID(model_id)
	{
		m_type = type;
		m_numberAvailable = 1;
	}

	~SubsystemResource()
	{}

	ResourceID
		GetDataListID()
			{Check_Object(this); return m_dataListID;}
	ResourceID
		GetGameModelID()
			{Check_Object(this); return m_modelID;}
	int
		GetSubsystemType()
			{Check_Object(this); return m_type;}
	int
		GetNumberAvailable()
			{Check_Object(this); return m_numberAvailable;}
	void
		AddNumberAvailable()
			{Check_Object(this); m_numberAvailable ++;}
	void
		RemoveNumberAvailable()
			{Check_Object(this); if(m_numberAvailable != -1) m_numberAvailable --;}
	void
		SetUnlimited()
			{Check_Object(this); m_numberAvailable = -1;}
	
protected:

	Adept::ResourceID
		m_dataListID;
	Adept::ResourceID
		m_modelID;
	int
		m_type;
	int
		m_numberAvailable;
};

class MechLab
{

public:

	MechLab();
	~MechLab();

	Mech *m_workingMech; // jcem - for mech
    Entity* m_workingEntity; // jcem - for cameraship...

	Stuff::MString
		m_workingMechName;
	ResourceID 
		*m_mechIDs;
	ResourceID 
		*m_chassisIDs;
	static ElementRenderer::CameraElement
		*s_MechCamera;
	ElementRenderer::GroupElement
		*m_sceneRoot;

	Stuff::SortedChainOf<SubsystemResource *, int> 
		m_subsystemsAvailable;

	enum{
		ChassisTabMode = 0,
		WeaponsTabMode,
		ArmorTabMode
	};
	enum{
		MissileWeapons = 0,
		ProjectileWeapons,
		BeamWeapons,
		AllWeapons
	};

	int
		m_mode;

	Stuff::SlotOf<Adept::ResourceFile *>
		m_mechResourceFile;

	static MechLab
		*Instance;
	static void _stdcall
		UpdateDisplay();
	void
		Execute();
	virtual int
		Exit();
	virtual void
		StartUp();
    void FreeReplicators();
	void
		ShutDown();
	virtual void
		ReInitialize() {}
	virtual void
		InitializeSubsystemsAvailable();
	SubsystemResource*
		AddAvailableSubsystem(const Adept::ResourceID& data_list, const Adept::ResourceID& model_id, int type);
	SubsystemResource*
		AddAvailableSubsystem(Subsystem *subsystem);
	bool
		DoesHaveAvailableSubsystem(int type);
	void
		RemoveAvailableSubsystem(int type);
	int
		SetMech(int mech_id, const char *mech_name, const char *path);
	int SetMech(ResourceID mech_resource_id, const char *mech_name, const char *path); // jcem
	int 
		SetMech(Adept::ResourceID mech_id);
	virtual int
		CreateNewMech(void *data[], int count, const char *path);
	virtual int
		SaveMech();
	virtual int
		SelectMech(void *data[], int count, const char *path);
	virtual void
		SetUpWorkingMech(Entity *entity);
	void
		MakeInteresting(Entity *entity);
	void
		MakeMoverInteresting(MWMover *mover);
	void
		MakeUnInteresting(Entity *entity);
	void
		MakeMoverUnInteresting(MWMover *mover);
	int
		GetDummyData(void *data[], int count);
	int
		DeleteMech();
	virtual int
		Restore();
	virtual int
		Rename(void *data[], int count, const char *path=NULL);

	//Functions to return Mech part subsystems
	int
		GetLeftArmWeapons(void *data[], int count);
	int
		GetRightArmWeapons(void *data[], int count);
	int
		GetLeftLegWeapons(void *data[], int count);
	int
		GetRightLegWeapons(void *data[], int count);
	int
		GetRightTorsoWeapons(void *data[], int count);
	int
		GetLeftTorsoWeapons(void *data[], int count);
	int
		GetCenterTorsoWeapons(void *data[], int count);
	int
		GetHeadWeapons(void *data[], int count);
	int
		GetSpecial1Weapons(void *data[], int count);
	int
		GetSpecial2Weapons(void *data[], int count);
	int
		FillPartWeaponData(int part_id, void *data[]);

	//Get the mech stuff
	virtual int 
		GetMechs(void *data[], int count);
	virtual int 
		GetChassis(void *data[], int count);
	virtual int
		GetChassisCount();
	virtual int
		GetMechCount();
	
	//Get the weapon lists
	int
		GetAllWeapons(void *data[], int count);
	int
		GetBeamWeapons(void *data[], int count);
	int 
		GetProjectileWeapons(void *data[], int count);
	int
		GetMissileWeapons(void *data[], int count);
	int
		FillWeaponListData(int weapon_list, void *data[]);

	//Get General Mech Data
	int
		GetCurrentMechData(void *data[], int count);
	int
		GetCurrentMechNoEditData(void *data[], int count);

	//Armor support
	int
		GetCurrentMechArmorData(void *data[], int count);
	int
		SetArmorType(void *data[], int count);
	int
		AddArmorZoneValue(void *data[], int count);
	int
		RemoveArmorZoneValue(void *data[], int count);
	int
		SetArmorValue(void *data[], int count);
	int
		DistributeAllArmor();
	

	//Init the 3 tabs
	int
		InitChassisTab(void *data[], int count);
	int
		InitWeaponsTab(void *data[], int count);
	int
		InitArmorTab(void *data[], int count);

	//The add stuff
	int
		AddSubsystem(void *data[], int count);
	virtual void
		AddSubsystemToMech(int *sub_type, int *zone, int *error);
	virtual int
		AutoAddSubsystem(void *data[], int count);
	int 
		RemoveSubsystem(void *data[], int count);
	virtual void
		RemoveWeaponFromMech(int *sub_id, int *zone);
	virtual void
		RemoveSubsystemFromMech(int *sub_type, int *zone);
	virtual int
		RemoveAllSubsystems();
	int
		FindInternalLocation(int slot_type, int slots_needed);

	//Weapon Groups
	int 
		SetAllWeaponGroups(void *data[], int count);
	int
		GetWeaponGroups(void *data[], int count);
	int 
		SetWeaponGroup(void *data[], int count);
	int
		ClearWeaponGroup(void *data[], int count);
	Weapon* 
		FindWeapon(int id);

	//Auxillary systems support
	int
		GetEngineSpeed(void *data[], int count);
	int
		UpgradeEngine();
	int
		DegradeEngine();
	int
		GetHeatSinkCount(void *data[], int count);
	int
		AddHeatSink();
	int
		RemoveHeatSink();
	int
		GetJumpJets(void *data[], int count);
	int
		SetJumpJets(void *data[], int count);
	int
		GetECM(void *data[], int count);
	int 
		SetECM(void *data[], int count);
	int 
		GetBeagle(void *data[], int count);
	int
		SetBeagle(void *data[], int count);
	int
		GetLightAmp(void *data[], int count);
	int
		SetLightAmp();
	int 
		GetAMS(void *data[], int count);
	int
		SetAMS();
	int 
		GetLAMS(void *data[], int count);
	int
		SetLAMS();
// MSL 5.02 SubSystems
//	int 
//		GetEnhancedOptics(void *data[], int count);
//	int
//		SetEnhancedOptics();
	int 
		GetIFF_Jammer(void *data[], int count);
	int
		SetIFF_Jammer();
	int 
		GetAdvancedGyro(void *data[], int count);
	int
		SetAdvancedGyro();


	//Skin Callbacks
	int
		GetSkinListCount(void *data[], int count);
	int
		GetSkinList(void *data[], int count);
	int
		SetMechSkin(void *data[], int count);

	//Ammo Callbacks
	int
		GetWeaponAmmo(void *data[], int count);
	int
		AddWeaponAmmo(void *data[], int count);
	int
		RemoveWeaponAmmo(void *data[], int count);

	int 
		GetBaseMechName(void *data[], int count);

	//Main Callback for GOS Script
	static int _stdcall ML_CallbackHandler(void* instance, int count, void* data[]);
    static int _stdcall ML_CallbackHandlerReal(void* instance, int count, void* data[]);

	//Variables that need to be registered
	int m_mechLabCount;
	int m_chassisCount;
	int m_isCampaign;

    // jcem for MechView
    Stuff::SafeChainOf<Replicator*> m_TempReplicators;
public: // jcem
    Mech* GetWorkingMech() const;
    Entity* GetWorkingEntity() const;
    void DestroyWorkingEntity();
};
