//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Compose.h"
#include "AudioTrack.h"
#include "MidiTrack.h"
//#include "StyleItem.h"
#include "Undo.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)

char* g_strUndoType[][16] = {
			{ "调节音量", "预设段落结构", "改变全局音色库" },
			{ "改变全局调号", "改变小节调号" },
			{ "修改和弦" },
			{ "删除音频", "复制音频", "移动音频", "导入音频片段", "录音", "局部音效处理" },
			{ "插入小节/段", "删除小节/段",	"移动小节/段", "改变小节/段风格" },
			{ "添加乐器织体", "删除乐器织体", "更换乐器织体", "更换织体音色" },
			{ "替换全曲风格", "调节段落音量", "调节织体音量" },
			{ "添加轨道音效", "删除轨道音效", "改变音效顺序", "调节音效参数" },
			{ "改变轨道状态", "调节轨道音量", "调节轨道声像", "调节轨道增益", "改变通道号" },
			{ "添加音频轨道", "删除音频轨道", "删除全部音频轨道", "显示音频轨道", "显示全部音频轨道",
																"隐藏音频轨道", "隐藏全部音频轨道" },
			{ "添加MIDI轨道", "删除MIDI轨道", "删除全部MIDI轨道", "显示MIDI轨道", "显示全部MIDI轨道",
																"隐藏MIDI轨道", "隐藏全部MIDI轨道" }

};
TUndo g_Undo;
//---------------------------------------------------------------------------

void DeleteList( TAudioTrackList* pList )
{
	while( !pList->empty() ){
		delete pList->back();
		pList->pop_back();
	}
}

void DeleteList( TMidiTrackList* pList )
{
	while( !pList->empty() ){
		delete pList->back();
		pList->pop_back();
	}
}

void DeleteList( TEffect* pList )
{
	TEffect * pE = pList;

	while( pE ){
		TEffect *pTemp = pE->pNext;
		delete pE;
		pE = pTemp;
	}
}

void DeleteList( TOpusStageList* pList )
{
	while( !pList->empty() ){
		delete pList->back();
		pList->pop_back();
	}
}

void TUndo::AddUndo( int iType, int iCode, int iBegin, int iEnd, void* pBefore, void* pAfter )
{
	RemoveLites( m_iPos++ );

	TUndoLite* pLite = new TUndoLite( iType, iCode, iBegin, iEnd );
	pLite->pBefore = pBefore;
	pLite->pAfter = pAfter;
	m_lstLites.push_back( pLite );
}
//---------------------------------------------------------------------------

void TUndo::SetUndoExtra( int iExt1, int iExt2, int iExt3, void* pExt1, void* pExt2 )
{
	TUndoLite* pLite = m_lstLites.back();
	pLite->iExt1 = iExt1;
	pLite->iExt2 = iExt2;
	pLite->iExt3 = iExt3;
	pLite->pExt1 = pExt1;
	pLite->pExt2 = pExt2;
}
//---------------------------------------------------------------------------

void TUndo::SetUndoCode( int iCode )
{
	TUndoLite* pLite = m_lstLites.back();
	pLite->iCode = iCode;
}
//---------------------------------------------------------------------------

void TUndo::CancelUndo()
{
	RemoveLites( --m_iPos );
}
//---------------------------------------------------------------------------

void TUndo::RemoveLites( int iFrom )
{
	while( m_lstLites.size()>iFrom ){
		TUndoLite* pLite = m_lstLites.back();
		DelLiteParams( pLite );
		delete pLite;
		m_lstLites.pop_back();
	}
}
//---------------------------------------------------------------------------

void TUndo::DelLiteParams( TUndoLite* pLite )
{
	if( pLite->iType==UNDO_KEY_BARS ){
		if( pLite->pBefore )
			delete[] (int*)pLite->pBefore;
	}
	else if( pLite->iType==UNDO_CHORD ){
		if( pLite->pBefore )
			delete[] (BYTE*)pLite->pBefore;
		if( pLite->pAfter )
			delete[] (BYTE*)pLite->pAfter;
	}
	else if( pLite->iType==UNDO_TRKAUD_DEL || pLite->iType==UNDO_TRKAUD_DELALL ){
		if( pLite->pBefore )
			DeleteList( (TAudioTrackList*)pLite->pBefore );
	}
	else if( pLite->iType>=UNDO_TRKAUD_SHOW && pLite->iType<=UNDO_TRKAUD_HIDEALL
				|| pLite->iType>=UNDO_TRKMID_SHOW && pLite->iType<=UNDO_TRKMID_HIDEALL ){
		if( pLite->pBefore )
			delete (vector<BYTE>*)pLite->pBefore;
	}
	else if( pLite->iType>=UNDO_AUDIO_ERASE && pLite->iType<=UNDO_AUDIO_FX ){
		if( pLite->iCode>0 ){
			if( pLite->pBefore )
				delete[] (DWORD*)pLite->pBefore;
			if( pLite->pAfter )
				delete[] (DWORD*)pLite->pAfter;
			if( pLite->pExt1 )
				delete[] (DWORD*)pLite->pExt1;
			if( pLite->pExt2 )
				delete[] (DWORD*)pLite->pExt2;
		}
		else {
			if( pLite->pBefore )
				delete (TAudioTrack*)pLite->pBefore;
			if( pLite->pAfter )
				delete (TAudioTrack*)pLite->pAfter;
			if( pLite->pExt1 )
				DeleteList( (TOpusStageList*)pLite->pExt1 );
			if( pLite->pExt2 )
				DeleteList( (TOpusStageList*)pLite->pExt2 );
		}
	}
	else if( pLite->iType>=UNDO_BAR_INSERT && pLite->iType<=UNDO_BAR_CHANGE
													|| pLite->iType==UNDO_OPUS_STYLE
													|| pLite->iType==UNDO_PRESET
													|| pLite->iType==UNDO_KEY_MELODY ){
		if( pLite->pBefore )
			DeleteList( (TOpusStageList*)pLite->pBefore );
		if( pLite->pAfter )
			DeleteList( (TOpusStageList*)pLite->pAfter );
		if( pLite->pExt1 )
			DeleteList( (TAudioTrackList*)pLite->pExt1 );
	}
	else if( pLite->iType>=UNDO_MIDI_ADD && pLite->iType<=UNDO_MIDI_FONT
								|| pLite->iType==UNDO_TRKMID_DEL ){
		if( pLite->pBefore )
			delete[] (TTrack*)pLite->pBefore;
		if( pLite->pAfter )
			delete (TTrack*)pLite->pAfter;
		if( pLite->pExt1 )
			delete (vector<DWORD>*)pLite->pExt1;
		if( pLite->pExt2 )
			delete (vector<DWORD>*)pLite->pExt2;
	}
	else if( pLite->iType==UNDO_TRKMID_DELALL ){
		if( pLite->pBefore )
			DeleteList( (TOpusStageList*)pLite->pBefore );
		if( pLite->pAfter )
			DeleteList( (TOpusStageList*)pLite->pAfter );
		if( pLite->pExt1 )
			DeleteList( (TMidiTrackList*)pLite->pExt1 );
	}
	else if( pLite->iType==UNDO_PROG_VOL ){
		if( pLite->pExt1 )
			delete (TTrack*)pLite->pExt1;
	}
	else if( pLite->iType>=UNDO_FX_ADD && pLite->iType<=UNDO_FX_MOVE ){
		if( pLite->pBefore )
			delete (TAudioFx*)pLite->pBefore;
		if( pLite->pAfter )
			delete (TAudioFx*)pLite->pAfter;
	}
	else if( pLite->iType==UNDO_FX_PARAM ){
		if( pLite->pBefore )
			delete (float*)pLite->pBefore;
		if( pLite->pAfter )
			delete (float*)pLite->pAfter;
	}
}


