//---------------------------------------------------------------------------

#ifndef MidiTrackH
#define MidiTrackH
//---------------------------------------------------------------------------
#include <vector>
#include "ProCommon.h"
using namespace std;
#include "StyleItem.h"
#include "BaseTrack.h"

/***************************************************************************************/
// TMidi
typedef struct tagMidiNote{
	BYTE pitch,	  	//音高
		velocity, 	//力度
		volume, 	//音量
		rsvd;
	int tkOn, tkOff;

	tagMidiNote( BYTE pt, BYTE vel, BYTE vol, DWORD on )
	{
		pitch = pt;
		velocity = vel;
		volume = vol;
		tkOn = on;
		tkOff = -1;

	};
} TMidiNote;

class TMidiTrack : public TBaseTrack
{
public:
	BYTE bank; //音源号 0xFF=全局SF2，other为指定音源
	BYTE chno; //通道号
	BYTE prog; //乐器号
	BYTE file; //文件号 处理乐器多于16种的情况

	BYTE ptMin, ptMax; //音符范围

	vector<int> aStages;
	vector<TMidiNote*> aNotes;

	TMidiTrack() : TBaseTrack()
	{
		bank = chno = prog = file = 0xFF;
	};

	TMidiTrack( BYTE bk, BYTE ch, BYTE pr, BYTE fi=0 ) : TBaseTrack()
	{
		bank = bk;
		chno = ch;
		prog = pr;
		file = fi;

		ptMin = 0xFF;
		ptMax = 0;
	};

	TMidiTrack( TMidiTrack* pSrc ) : TBaseTrack( pSrc->state, pSrc->volume, pSrc->pan, pSrc->gain )
	{
		bank = pSrc->bank;
		chno = pSrc->chno;
		prog = pSrc->prog;
		file = pSrc->file;

		ptMin = 0xFF;
		ptMax = 0;
	}

	void AddStage( int iStage )
	{
		if( aStages.empty() )
			aStages.push_back( iStage );
		else{
			for( int i=aStages.size()-1; i>=0; i-- ){
				if( aStages[i]<iStage ){
					if( i+1>=aStages.size() )
						aStages.push_back( iStage );
					else
						aStages.insert( aStages.begin()+i+1, iStage );

					break;
				}

				if( aStages[i]==iStage )
					break;

				if( i==0 ){
					aStages.insert( aStages.begin(), iStage );
					break;
				}
			}
		}
	};

	void DelStage( int iStage )
	{
		for( int i=0; i<aStages.size(); i++ ){
			if( aStages[i]>iStage )
				break;

			if( aStages[i]==iStage ){
				aStages.erase( aStages.begin() + i );
				break;
			}
		}
	};

	bool ValidStages( vector<int>& lstStages ) //段落可用
	{
		bool bValid = true;
		vector<int>::iterator iter1 = aStages.begin(),
				iter2 = lstStages.begin();
		while( iter1!=aStages.end() && iter2!=lstStages.end() ){
			if( *iter1 < *iter2 )
				iter1++;
			else if( *iter1 > *iter2 )
				iter2++;
			else{
				bValid = false;
				break;
			}
		}

		return bValid;
	};

	bool IsDrum()
	{
		if( !aStages.empty() ){
			TOpusStage* pStage = g_lstOpusStages[aStages[0]];
			for( int i=0; i<pStage->aTracks.size(); i++ ){
				TTrack* pTrack = pStage->aTracks[i];
				if( pTrack->iFile==file && pTrack->iChanSpec==chno && pTrack->iChanNo==9 )
					return true;
			}
		}

		return false;
	}
};

typedef struct tagChnoUsed
{
	WORD chno; //通道号按位占用
	BYTE file; //文件号 处理乐器多于16种的情况
	BYTE bank; //音源号 0xFF=全局SF2，other为指定音源

	tagChnoUsed( BYTE bk, BYTE fi=0 )
	{
		bank = bk;
		file = fi;
		chno = 0;
	}
} TChnoUsed, *PTChnoUsed;

typedef vector<TMidiTrack*> TMidiTrackList;

class TMidi
{
private:
	TMidiTrackList		m_lstMidiTracks;		//MIDI轨道列表
	vector<PTChnoUsed> 	m_aChnoUsed;
	int					m_nMidiFile;


public:
	TMidi(){m_nMidiFile = 0;};
	~TMidi(){ClearMidiTracks();};

	TMidiTrackList& MidiTrackList() { return m_lstMidiTracks; };
	bool IsEmpty() { return m_lstMidiTracks.empty(); };
	void ClearMidiTracks();
	void ClearMidiTrackNotes();
	int ClearEmptyTrack();

	void SortMidiTracks(); //整理channel号

	int GetMidiTrackIndex( BYTE file, BYTE chno );
	TMidiTrack* FindMidiTrack( BYTE file, BYTE chno );
	TMidiTrack* GetValidMidiTrack( vector<int>& lstStages, BYTE file, BYTE chno, BYTE bank, BYTE prog );
 	TMidiTrack* GetValidMidiTrack( int iStage, BYTE file, BYTE chno, BYTE bank, BYTE prog );

	void CutStage( int iStage ); //分割段
	void InsertStage( int iStage ); //插入空段
	void RemoveStage( int iStage, bool bSort ); //删除段 bSort=不留空

	TChnoUsed* GetChnoUsed( BYTE file, BYTE bank );
	void AddMidiTrack( TMidiTrack* pCh, int iInd=-1 );
	void AddChnoUsed( TChnoUsed* pCU );
	void DeleteMidiTrack( TMidiTrack* pCh );
	void DeleteChnoUsed( TChnoUsed* pCU );
	BYTE GetValidFile( BYTE bank, BYTE chno );
	void ChangMidiChno( int iMT, BYTE fiNew, BYTE chNew );

	void InitNoteColor();
	TColor GetNoteColor( int vol );
	void ChangeNotesVolume( int iMT, int iSBar, int iEBar, BYTE volume );

	void GetSpecBanks( vector<BYTE>& lstBank );
	void SetSpecBanks( BANKMAPLIST& lstMap );
	void WriteProj( FILE* pFile );
	int ReadProj( FILE* pFile, DWORD dwVersion );
};

/***************************************************************************************/
// 全局变量
/***************************************************************************************/
extern TMidi				g_Midi;					//MIDI轨道对象
extern TMidiTrackList&		g_aMidiTracks;		//MIDI轨道列表
extern int					g_iSelMidiTrack;		//当前处理的MIDI轨道

#endif
