#if !defined(__MREPLAY2_H__)
#define __MREPLAY2_H__

#define MAX_MRP_PACK_PER_FRAME  1000

#define MRP_ADD_PLAYER_NAME             1000
#define MRP_REMOVE_PLAYER_NAME          1001
#define MRP_STOP_FRAME                  2000
#define MRP_FULLCONFIRM                 2001
#define MRP_RESPAWNMESSAGEID            2002
#define MRP_MECHDAMAGETAKEN             3000

extern const char* g_pcszGameDataExtMR;

#pragma pack(push, 4)

struct SMRP_PLAYER_NAME
{
public:
    DPID m_dpId;
    char m_szName[1];
};

#pragma pack(push, 1)
struct SMRP_MECH_DAMAGETAKEN
{
public:
    Stuff::Scalar m_fDamage;
    BYTE m_bCon1;
    BYTE m_weaponID;
    WORD m_wLID1; //ReplicatorID m_id1;
    BYTE m_bCon2;
    BYTE m_damageType;
    WORD m_wLID2; //ReplicatorID m_id2;
};
#pragma pack(pop)

struct SMRP
{
public:
    int m_nCommand; // 
    union {
    int m_nType; // 
    DWORD m_dpID;
    float m_fFrameTime;
    };
    int m_nLen; // 
    union {
    BYTE m_ba[0];
    SMRP_PLAYER_NAME m_PlayerName[0];
    SMRP_MECH_DAMAGETAKEN m_MDT[0];
    };
public:
    int GetMemSize() const;
};
typedef SMRP* PMRP;

class CMRPPack;
CMRPPack* AllocMRPPack(int nCount, PMRP* ppMRP);
void FreeMRPPack(CMRPPack* pMRPPack);

class CMRPPack
{
public:
    CMRPPack* m_pPrev;
    CMRPPack* m_pNext;
    float m_fFrameTime;
    int m_nCount;
    PMRP m_pa[0];
public:
    void Construct(int nCount, PMRP* ppMRP);
    void Destruct();
    int GetMemSize() const;
    void Save(Stuff::DynamicMemoryStream& mf);
    void Load(Stuff::MemoryStream& mf, DWORD dwMeta);
};

class CMRPPlayer
{
public:
    CMRPPlayer* m_pPrev;
    CMRPPlayer* m_pNext;
    bool m_bBOT;
    MString m_strName;
    MString m_strClan;
    MString m_strScript;
    BYTE m_connection_id;
	int m_pilotTeam;				// the team the pilot is on
	int m_pilotDecals;			// the index of their pilot decal
	int m_teamDecals;				// the index of their team decal
	int m_mechChasisID;			// what mech they are in
	char m_pilotSkins;				// the skin prefix
    int m_tonnage;
    // for bot only - start
    Adept::ResourceID m_aiModel;
    // for bot only - end
    BYTE* m_pBufVCM;
    Stuff::MemoryStream* m_vehicleCreateMessage;
public:
    CMRPPlayer();
    ~CMRPPlayer();
    int GetMemSize() const;
    void Save(Stuff::DynamicMemoryStream& mf);
    void Load(Stuff::MemoryStream& mf);
};
typedef CMRPPlayer* PMRPPlayer;

class CMRPFull
{
public:
    DPSESSIONDESC2 m_CurrentSession;
    MString m_strGameName;
    DWORD m_dwMyDirectPlayID;
    MString m_strPlayer;
    MString m_strPassword;

    bool m_bStarting;
    bool m_bStarted;
    bool m_bStopping;
    bool m_bStopped;
    int m_nMissionParamSize;
    BYTE* m_pMissionParam;
    bool m_bTeamGame;

    int m_nBOTPlayers;
    int m_nLoadingPlayers;
    int m_nBroadCastPlayers;

    CMRPPlayer* m_pMRPPlayers;

    float m_fFrameTime;
    int m_nCount;
    PMRP m_pa[MAX_MRP_PACK_PER_FRAME];

    CMRPPack* m_pMRPPackStart;
    CMRPPack* m_pCurMRPPack;
    PMRP m_pLastDictionary;
    PMRP m_pLastDictionaryToBeSent;
public:
    CMRPFull();
    ~CMRPFull();
    static MWApplication* Check();
    bool IsValidData() const;
    void Reset();
    bool IsValid() const;
    void Loading();
    void Loaded();
    void PreRendering();
    void PreRendered();
    void Starting();
    void Started();
    void StartFrame();
    void StopFrame();
    void ReduceFrame();
    void Stopping();
    void Stopped();
    PMRPPlayer AddMRPPlayer(bool bBOT);
    PMRP AddMRP(int nCommand, int nType, int nLen);
    void OnGameOpen(const char* pcszGameName, DWORD dwMyID, const char* pcszPlayer, const char* pcszPassword);
    void OnGameClose();
    void AddRemovePlayerToGame(int nCommand, char* Name, DPID dpId);
    void AddRemoveConnection(bool bAdd, Connection* pConnection);
    void SessionLost();
    void* NetInformation(gosNetInfo Info, DWORD Parameter, char* Name);
    void NetServerCommands(gos_NetCommands Command, DWORD Data1);
    NetPacket* NetGetMessage();
    bool LocalSendNetMessage(int message_type, Stuff::MemoryStream& message);
    void BackgroundTack();
    PMRP SendMessage(int message_type, Stuff::MemoryStream *message, int nCommand = 0);
    void MechDamageTaken(ReplicatorID mech1, ReplicatorID mech2, Stuff::Scalar damage_taken, int weaponID, int damageType);
    void _cdecl SendCommand(int nCommand, ...);
    void DoReplay();
    void QuitReplay();
    int GetMemSize() const;
    void DbgReport() const;
    bool SaveMR(const char* pcszFile);
    bool LoadDefaultMR();
    bool LoadMR(const char* pcszFile);
    Stuff::Scalar EndMissionTime() const;
};

#pragma pack(pop)

void MRP_Setup();
void MRP_Cleanup();

extern CMRPFull g_MRF;

#endif // !defined(__MREPLAY2_H__)
