//---------------------------------------------------------------------------
#ifndef ComposeH
#define ComposeH
//---------------------------------------------------------------------------

#include <vector>
#include "ProCommon.h"
using namespace std;

#define POINTS_PER_BAR 120   //每小节点数

#define SEGTYPE_VAR				0
#define SEGTYPE_FILL			1
#define SEGTYPE_INTRO			2
#define SEGTYPE_ENDING			3

#define CHECK_GET 		0x0000
#define CHECK_STAGE		0x0001
#define CHECK_TRACK		0x0002
#define CHECK_CHORD		0x0004
#define CHECK_KEY		0x0008
#define CHECK_PROG		0x0010
#define CHECK_STAGEALL  0x001F
#define CHECK_VOL		0x0020
#define CHECK_ALL		0x00FF

/***************************************************************************************/
// 全局类定义
/***************************************************************************************/
// TCompose
typedef struct tagBar0
{
	//每小节最多POINTS_PER_BAR个音量值
	DWORD aVols[POINTS_PER_BAR];
	bool aRecording[POINTS_PER_BAR];
	TBarChords aChords;
	bool bInvalid; // 是否无效

	tagBar0()
	{
		bInvalid = false;
		memset( this, 0, sizeof(tagBar0) );
	}

	tagBar0( tagBar0* pSrc )
	{
		memcpy( this, pSrc, sizeof(tagBar0));
	}
} TBarOld, *PTBarOld;

typedef struct tagBar
{
	TBarChords aChords;  //和弦
	char iBarKey; // 小节的调号
	char reserved[3]; // 保留字段，对齐字节

	tagBar()
	{
		memset( this, 0, sizeof(tagBar) );
		iBarKey = -1;
	}

	tagBar( tagBar* pSrc )
	{
		memcpy( this, pSrc, sizeof(tagBar));
	}
} TBar, *PTBar;

typedef vector<TTrack*> TTrackList;
typedef vector<TBar*> TBarList;

typedef struct tagOpusStage //曲式分段信息
{
	char iSegType;			//片段类型 0=VAR, 1=FILL, 2=INTRO, 3=ENDING
	char iSegNo;     		//最初片段号
	char iSegKey;			//分段调号
	char nVol; 				//段落音量
	TBarList aBars;         //小节列表
	TTrackList aTracks; 	//轨道数列表

	tagOpusStage(){
		iSegKey = iSegType = iSegNo = -1;
		nVol = 100;
	}

	tagOpusStage( tagOpusStage* pSrc ){
		iSegType = pSrc->iSegType;
		iSegNo = pSrc->iSegNo;
 		iSegKey = pSrc->iSegKey;
		nVol = pSrc->nVol;
	}

	~tagOpusStage(){
		while( !aBars.empty() ){
			delete aBars.back();
			aBars.pop_back();
		}
		while( !aTracks.empty() ){
			delete aTracks.back();
			aTracks.pop_back();
		}
	}
} TOpusStage, *PTOpusStage;

typedef vector<TOpusStage*> TOpusStageList;
typedef vector<TPROSTYLE*> STYLELIST;
typedef vector<TStage*> TStageList;

typedef struct{
	UINT idLoc;
	UINT idStyle;
	vector<DWORD> aSegs;
} TLocSegment;

typedef vector<TLocSegment*> LOCSEGLIST;

typedef struct{
	BYTE iBankOld;
	BYTE iBankNew;
} TBankMap;

typedef vector<TBankMap*> BANKMAPLIST;

class TCompose
{
protected:
	UINT m_idLoc, m_idStyle;
	int m_nBarCount;

	TOpusStageList m_lstStages;
	void ClearStages();

public:
	virtual void Clear();
	int StageCount() { return m_lstStages.size(); };
	TOpusStage* CopyStageAt( int iStage );
	TOpusStageList& StageList() { return m_lstStages; };
	virtual void Set( UINT idLoc, UINT idStyle, TOpusStageList& lstStages );
	virtual void Get( UINT& idLoc, UINT& idStyle, TOpusStageList& lstStages );
	int BarCount() { return m_nBarCount; };

	virtual void WriteProj( LOCSEGLIST& lstLocSeg, FILE* pFile );
	virtual int ReadProj( STYLELIST& aUnsolvedStyles, FILE* pFile, DWORD dwVersion );
	void SetTempStyle( UINT idLoc, UINT idStyle, int idSet );
	void GetSpecBanks( vector<BYTE>& lstBank );
	void SetSpecBanks( BANKMAPLIST& lstMap );

	TCompose() {
		m_idLoc = m_idStyle = -1;
		m_nBarCount = 0;
	};

	~TCompose() {
		Clear();
	};
};

class TTheme : public TCompose
{
private:
	bool m_bWeakup;
	int m_iKey;

public:
	bool Empty() { return m_lstStages.empty(); };
	bool IsWeadup() { return m_bWeakup; };
	TBar* GetFirstBar() { return m_lstStages[0]->aBars[0]; };
	int GetKey(){ return m_iKey; };

	virtual void Clear();
	virtual void Set( UINT idLoc, UINT idStyle, TOpusStageList& lstStages );
	virtual void WriteProj( LOCSEGLIST& lstLocSeg, FILE* pFile );
	virtual int ReadProj( STYLELIST& aUnsolvedStyles, FILE* pFile, DWORD dwVersion );

	void Build( TBarList& lstBars, vector<int>&lstStages );
	int GetFirstChord();
	int GetLastChord();
	void Set( TOpusStageList& lstStages );


	TTheme();
};

class TOpus : public TCompose
{
private:
	BOOL m_bModified;
	TOpusStageList m_lstStagesBk;
	int m_iKeyBk;
	vector<DWORD> m_aStageBars;

public:
	TOpus();
	~TOpus();

	virtual void Clear();
 	virtual void Set( UINT idLoc, UINT idStyle, TOpusStageList& lstStages );
	virtual void WriteProj( LOCSEGLIST& lstLocSeg, FILE* pFile );
	virtual int ReadProj( STYLELIST& aUnsolvedStyles, FILE* pFile, DWORD dwVersion );

	void ClearBackup();
	void CopyStages( int iStartBar, int iEndBar, TOpusStageList* lstStages );
	void Backup();
	void Restore();
	BOOL CheckModified( int iCheckType );
	void BuildStyleItem();
	void ChangeKey( int iBarStart, int iBarEnd, int iKey, int keys[] );
	void CountBars();
	int FindStage( int iBar, int *piFirstBar );
	int StageFirstBar( int iStage );
	int StageLastBar( int iStage );
	DWORD StageRange( int iStage );
	void InsertStage( int iIns, TOpusStage* pStage );
	void RemoveStage( int iDel );
	void CutStage( int iStage, int iCutBar );
	void ChangeStageBar( int iStage, int nBar, bool bCount );
};


/***************************************************************************************/
// 全局变量
/***************************************************************************************/
extern int					g_iPreStage,			// 预设段落模式
							g_iMelodyKey;			// 主旋律调号

extern float				g_fMusicVolume;       	//伴奏音量
extern bool					g_bComposeMute; 		//伴奏静音

extern TTheme				g_Theme;				//主旋律对象
extern TOpus				g_Opus;					//全曲对象
extern TOpusStageList&      g_lstOpusStages;		//曲式结构段落表

extern vector<UINT>			g_lstPaidStyleIDs;		//当前工程本次使用已支付风格ID列表

/***************************************************************************************/
// 全局函数
/***************************************************************************************/

int FindStage( int iBar, int *piFirstBar=NULL );
int FirstBar( int iStage );
int GetBarCount();
int GetBarKey( int iBar );
TOpusStage* DuplicateStage( TOpusStage* pSrc );
void ProduceTracks( TOpusStage* pStage, void* pSegItem );
bool DiffStages( TOpusStage* pStage1, TOpusStage* pStage2, bool bPassSegNo=false,
																	bool bPassFile=true );
#endif
