#if !defined(__RECSCORE_H__)
#define __RECSCORE_H__

#define MAX_SCORE_PACK 100
#define MAX_SCORE_PACK_PER_FRAME 2000

struct SRecScore;
class CRecScorePack;
class CRecScoreObject;
class CRecScoreFull;

extern const char* g_pcszGameDataSavePath;
extern const char* g_pcszGameDataExtPR;

void GetFileName4GUID(char szBuf[256], const char* pcszPath, const char* pcszExt, const GUID& guid = *(const GUID*)NULL);

#define MW4PRINT_COPYDATA_META 0xf4f72a54

#pragma pack(push, 1)
class MW4PRINT_COPYDATASTRUCT : public COPYDATASTRUCT
{
public:
    GUID m_GUID;
    char m_szFile[256];
};
#pragma pack(pop)

#pragma pack(push, 4)

union PART_WHERE
{
public:
    int m_nWhere;
    struct {
    int m_xWhere: 8;
    int m_xMasks: 24;
    };
public:
    void SetWhere(int nWhere);
    void SetMask(int nWhere);
};

struct SRecScore
{
public:
    int m_nType; // CBucketManager::Bucket_Type
    ReplicatorID m_who;
    ReplicatorID m_whom;
    int m_nBy;
    PART_WHERE m_Where;
    union {
    DWORD m_dwParam;
    int m_nParam;
    void* m_pParam;
    float m_fTime;
    };
};

class CRecScorePack
{
public:
    CRecScorePack* m_pPrev;
    CRecScorePack* m_pNext;
    int m_nCount;
    SRecScore m_a[MAX_SCORE_PACK];
public:
    CRecScorePack();
    ~CRecScorePack();
    int GetMemSize() const;
    void Save(DynamicMemoryStream& mf);
    void Load(MemoryStream& mf);
};

class CRecScoreFull;

class CRecScoreObject
{
public:
    CRecScoreFull* m_pRSF;
    CRecScoreObject* m_pPrev;
    CRecScoreObject* m_pNext;
    bool m_bRemoved;
    // player info
    bool m_bBOT;
    ReplicatorID m_who;
    MString m_strName;
    MString m_strMech;
    // Mech Info...
    int m_nPilotTeam;
    int m_nTeamDecal;
    int m_nPilotDecal;
    // Score...
    int m_nScore;
    int m_nKills;
    int m_nDeaths;
public:
    CRecScoreObject(CRecScoreFull* pRSF);
#if !defined(MW4PRINT)
    CRecScoreObject(CRecScoreFull* pRSF, const Mech* pMech, const char* pcszName, const char* pcszMech, int nPilotTeam, int nTeamDecal, int nPilotDecal);
#endif // !defined(MW4PRINT)
    ~CRecScoreObject();
    const char* GetName() const;
    const char* GetMech() const;
    bool CheckRemove();
    int GetMemSize() const;
    void Save(DynamicMemoryStream& mf, DWORD dwMeta);
    void Load(MemoryStream& mf, DWORD dwMeta);
};
typedef CRecScoreObject* PRecScoreObject;
typedef const CRecScoreObject* PCRecScoreObject;

class CRecScoreFull
{
public:
    int m_nState;
    SYSTEMTIME m_SysTime;

    int m_nMissionParamSize;
    BYTE* m_pMissionParam;
    bool m_bTeamGame;

    CRecScoreObject* m_pScoreObjects;

    int m_nCount;
    float m_fFrameTime;
    int m_naTeamScores[8];

    CRecScorePack* m_pScorePackStart;

    struct SPVP_Rec
    {
    public:
        ReplicatorID m_Inf;
        ReplicatorID m_Rcv;
        int m_nKills;
        int m_nScore;
    };
    int m_nPVPs;
    SPVP_Rec* m_pPVPs;
public:
	static int s_nLang;
public:
    CRecScoreFull();
    ~CRecScoreFull();
	static void CheckLanguage();
#if !defined(MW4PRINT)
    static MWApplication* Check();
#endif // !defined(MW4PRINT)
    bool IsValidData() const;
    void Reset();
    void Loading();
    void Loaded();
    void Starting();
    void Started();
    void StartFrame();
    void StopFrame();
    void ReduceFrame();
    void Stopping();
    void Stopped();
    int GetTotalRECs() const;
    int CalcKillsAndDeaths(ReplicatorID who, ReplicatorID whom) const;
    int CalcKillsAndDeathsForTeam(int nTeam, ReplicatorID id, bool bKill) const;
    int GetTeamScore(int nTeam) const;
    int RelativeGetScore4Player(const ReplicatorID& me, const ReplicatorID& whom, int& nKills, int& nDeaths) const; // jcem
    void Snap();
    CRecScoreObject& FindReplicatorID(ReplicatorID who) const;
#if !defined(MW4PRINT)
    void AddScoreObject(Mech* pMech, const char* pcszName, int nPilotTeam, int nTeamDecal, int nPilotDecal);
    void RemoveScoreObject(Mech* pMech);
#endif // !defined(MW4PRINT)
    SRecScore* AddRecScore();
    void RecScore(int nType, ReplicatorID who, ReplicatorID whom = ReplicatorID::Null, int nBy = 0, int nWhere = 0, DWORD dwParam = 0);
#ifdef _DEBUG
    void AddString(const SRecScore& RS) const;
#endif // _DEBUG
    int AddString(MString& str, const SRecScore& RS, const CRecScoreObject& For) const;
    MString* MakeInfoTable(PCRecScoreObject aRSOs[], int nPlayers, const int naTeams[8], int nTeamCount) const;
    int DoPrint() const;
    bool CheckTableFont(HDC hDC, const RECT& rcDraw, const POINT& DPI, const MString* pInfoTable, int nPlayers, int nTeamCount, int naColWidths[], int& nCellTextHeight) const;
    void DrawTable(HDC hDC, const MString* pInfoTable, const int naX[], const int naY[], const int nTableCols, const int nTableRows, const int nInvCol, const int nInvRow) const;
    void DoPrint(HDC hDC, const RECT& rcDraw, const POINT& DPI, int nCurPlayer, const MString* pInfoTable, const int naColWidths[], int nCellTextHeight, int nRow, PCRecScoreObject aRSOs[], int nPlayers, const int naTeams[8], int nTeamCount, int nTotals, const void* pParams) const;
    int GetMemSize() const;
    bool SavePR(const char* pcszFile);
    bool LoadPR(const char* pcszFile);
    void LoadPrintParams() const;
    void LoadPrintParam(const char* pcszINI, const char* pcszKey, long& lValue, int nDef, int nMin, int nMax) const;
    void LoadPrintParam(const char* pcszINI, const char* pcszKey, int& nValue, int nDef, int nMin, int nMax) const;
};

#pragma pack(pop)

extern CRecScoreFull g_RSF;

#endif // !defined(__RECSCORE_H__)
