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

#include "ListViewPattern.h"
#include "GlobalUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
#define LP_ITEM_OVER		RGB(67, 73, 80)
#define LP_ITEM_SELECTED	RGB(0, 0, 0)
#define LP_ITEM_DEF			RGB(39, 42, 47)
#define CELL_HEIGHT         18

#define LINE_COLOR			RGB(123, 123, 123)
#define FontClolor  		TColor(0xBDAA9C)

const BYTE u_arrChordPreset[2][4][4] = { //预设和弦
			{{0,37,9,30},{0,37,20,28},{0,9,20,28},{0,17,37,30}},
			{{37,9,28,16},{37,17,20,28},{37,0,9,17},{37,28,20,16}} };

TPngImage *pngCol   = NULL;
TPngImage *pngUnCol = NULL;
TPngImage *pngCharge = NULL;
void LoadImg()
{
	if( !pngCol )    pngCol   = new TPngImage();
	if( !pngUnCol )  pngUnCol = new TPngImage();
	if( !pngCharge ) pngCharge = new TPngImage();

	pngCol->LoadFromResourceName(int(HInstance), L"imgCollect");
	pngUnCol->LoadFromResourceName(int(HInstance), L"imgUnCollect");
	pngCharge->LoadFromResourceName(int(HInstance), L"imgStyleCharge");
}
void ReleaseImg()
{
	SAFE_DELETE(pngCol);
	SAFE_DELETE(pngUnCol);
	SAFE_DELETE(pngCharge);
}
//---------------------------------------------------------------------------
__fastcall TListViewPattern::TListViewPattern(TComponent* Owner, bool bChan9,
											TStageList* lstStages, int iPlayBar)
		: TListViewBase( Owner )
{
	m_nPlayIndex = -1;
	m_iFont = -1;
	m_iProg = -1;
	m_pPtInfo = NULL;

	m_bChan9 = bChan9;
	m_iPlayBar = iPlayBar;
	m_lstStages = lstStages;
	FOnTextureChanged = NULL;

	ShowHint = true;
	m_btnHint = NULL;

	LoadImg();
}
//---------------------------------------------------------------------------
__fastcall TListViewPattern::~TListViewPattern()
{
	ReleaseImg();
}
//---------------------------------------------------------------------------
int __fastcall TListViewPattern::DoCellHgt(TTableView *Sender, int iCellIndex)
{
	return CELL_HEIGHT;
}
//---------------------------------------------------------------------------
int __fastcall TListViewPattern::DoMDNum(TTableView *Sender)
{
	NULL_RETURN0(m_LstParttern)
	return m_LstParttern->size();
}
//---------------------------------------------------------------------------
int  __fastcall TListViewPattern::DoCellData(TStateBtn *sender)
{
	NULL_RETURN0(m_LstParttern)
	sender->SetData((void *)((*m_LstParttern)[sender->Index]));
}
//---------------------------------------------------------------------------
void __fastcall TListViewPattern::DoCellDraw(TStateBtn *sender, int BsTmp, TRect rtTmp, TCanvas *pCanvas)
{
	TStateBtn *pBtn  = (TStateBtn *)sender;
	TTextureInfo *pPtInfo  = (TTextureInfo*)pBtn->m_Data;

	if( Bs_NORMAL==BsTmp ) {
		 pCanvas->Brush->Color = LP_ITEM_DEF;
	}else if( Bs_ENTER==BsTmp ){
		 pCanvas->Brush->Color = LP_ITEM_OVER;
	}else if( Bs_DOWN==BsTmp ){
		 pCanvas->Brush->Color = LP_ITEM_SELECTED;
	}

	if( BsTmp==Bs_NORMAL || BsTmp==Bs_ENTER || BsTmp==Bs_DOWN ) {
		pCanvas->FillRect(rtTmp);

		int iLeft, iTop;
		TSize sizeFont;
		String strText;

		pCanvas->Brush->Style = bsClear;
		pCanvas->Font->Color = GetSegmentColor( pPtInfo->segType, 0, false );

		//绘制乐器
		if( !m_bChan9 ) strText  = GM_INSTRUMENT[pPtInfo->prog];
		else           strText  = L"GM鼓";
		sizeFont = pCanvas->TextExtent( strText );
		iLeft    = LEFT_CAPTION+(WIDTH_PROG(Width)-sizeFont.Width)/2;
		iTop     = rtTmp.Top+(rtTmp.Height()-sizeFont.Height)/2;
		pCanvas->TextOutW(iLeft, iTop, strText);
		pCanvas->Pen->Color = LINE_COLOR;
		pCanvas->MoveTo( LEFT_CAPTION+WIDTH_PROG(Width)+WIDTH_LINE/2 , rtTmp.Top);
		pCanvas->LineTo( LEFT_CAPTION+WIDTH_PROG(Width)+WIDTH_LINE/2, rtTmp.Bottom);

		String oriFontName = pCanvas->Font->Name;
		pCanvas->Font->Name = "Times New Roman";

		//绘制风格id号
		char styleID[256];
		if( pPtInfo->idLoc==0 )
			sprintf(styleID, "[%d]", pPtInfo->idStyle);
		else if( pPtInfo->idLoc==1 )
			sprintf(styleID, "[S%d]", pPtInfo->idStyle);
		else if( pPtInfo->idLoc!=(UINT)-1 )
			sprintf( styleID, "[L%d] ", LOWORD(pPtInfo->idStyle) );

		iLeft = LEFT_STYLE(Width);
		strText  = styleID;
		sizeFont = pCanvas->TextExtent( strText );
		iLeft    = LEFT_STYLE(Width)+(WIDTH_STYLE(Width)-sizeFont.Width)/2;
		iTop     = rtTmp.Top+(rtTmp.Height()-sizeFont.Height)/2;
		pCanvas->TextOutW(iLeft, iTop, strText);

		pCanvas->Pen->Color = LINE_COLOR;
		pCanvas->MoveTo( LEFT_STYLE(Width)+WIDTH_STYLE(Width)+WIDTH_LINE/2 , rtTmp.Top);
		pCanvas->LineTo( LEFT_STYLE(Width)+WIDTH_STYLE(Width)+WIDTH_LINE/2 , rtTmp.Bottom);

		//绘制伴奏类型
		char segName[256];
		sprintf(segName, "[%s-%d]", NAME_SEG[pPtInfo->segType], pPtInfo->segNo+1);
		strText  = segName;
		sizeFont = pCanvas->TextExtent( strText );
		iLeft    = LEFT_SEG(Width)+(WIDTH_SEG(Width)-sizeFont.Width)/2;
		iTop     = rtTmp.Top+(rtTmp.Height()-sizeFont.Height)/2;

		pCanvas->TextOutW(iLeft, iTop, strText);

		pCanvas->Pen->Color = LINE_COLOR;
		pCanvas->MoveTo( LEFT_SEG(Width)+WIDTH_SEG(Width)+WIDTH_LINE/2 , rtTmp.Top);
		pCanvas->LineTo( LEFT_SEG(Width)+WIDTH_SEG(Width)+WIDTH_LINE/2 , rtTmp.Bottom);

		pCanvas->Font->Name = oriFontName;
	}
}
//---------------------------------------------------------------------------
void __fastcall TListViewPattern::DoIconDraw(TStateBtn *sender, int BsTmp, TRect rtTmp, TCanvas *pCanvas)
{
	TStateBtn *pBtn   = (TStateBtn *)sender;
	TStateBtn *pCell  =  pBtn->m_PAR;
	TTextureInfo *info  = (TTextureInfo*)pCell->m_Data;
	TPngImage *pIMG  = NULL;
	String sHint;

	if(sender->Index==0) {
		pIMG = info->bCollected?pngCol:pngUnCol;
		if(BsTmp==Bs_ENTER ) {
			sHint = info->bCollected ? "点击取消收藏" : "点击收藏";
		}
	}
	else if(sender->Index==1) {
		TPROSTYLE* styleInfo = GetStyleInfo( info->idLoc, info->idStyle );
		if( styleInfo && styleInfo->idLoc==0 && styleInfo->pOrigin->cost>0 ) {
			pIMG = pngCharge;
			if(BsTmp==Bs_ENTER ) {
				sHint = "收费：";
				sHint += IntToStr( styleInfo->pOrigin->cost );
				sHint += "唱作音符";
			}
		}
	}

	if( pIMG ) {
		int iWidth  = pIMG->Width/3;
		int nTrans  = BsTmp==Bs_NORMAL ? 0
						: BsTmp==Bs_ENTER  ? (-iWidth)
						: BsTmp==Bs_DOWN   ? (-2*iWidth)
						: (-3*iWidth);

		if( Bs_NORMAL==BsTmp ||	Bs_ENTER==BsTmp || Bs_DOWN==BsTmp )	{
			HRGN rgnClip = CreateRectRgn( rtTmp.Left, rtTmp.Top,
				rtTmp.Left+rtTmp.Width(), rtTmp.Top+rtTmp.Height() );

			SelectClipRgn( pCanvas->Handle, rgnClip );
			pCanvas->Draw(rtTmp.Left+nTrans, rtTmp.Top, pIMG);
			SelectClipRgn( pCanvas->Handle, NULL );
			DeleteObject(rgnClip);
		}
	}

	if( sHint.Length() ){
		m_btnHint = sender;
		Hint = sHint;
	}
	else if(m_btnHint==sender ){
		m_btnHint = NULL;
		Hint = "";
		Application->CancelHint();
	}
}
//---------------------------------------------------------------------------
int  __fastcall TListViewPattern::DoIconsNum(TStateBtn *parent)
{
	return 2;
}
//---------------------------------------------------------------------------
int  __fastcall TListViewPattern::DoIconsBounds(TStateBtn *sender, TRect &rtBounds)
{
	int iLeft, iTop, iWidth, iHeight;

	if(sender->Index==0) {

		iLeft   = Width - WIDTH_SB - WIDTH_IMG_COL;
		iTop    = (CELL_HEIGHT - 15) / 2;
		iWidth  = 21;
		iHeight = 15;
	}
	else if(sender->Index==1) {

		iLeft   = LEFT_SEG(Width) - WIDTH_IMG_CHARGE - 1;
		iTop    = (CELL_HEIGHT - pngCharge->Height)/2;
		iWidth  = pngCharge->Width/3;
		iHeight = pngCharge->Height;
	}

	rtBounds = TRect(iLeft, iTop, iLeft+iWidth, iTop+iHeight);
}
//---------------------------------------------------------------------------
void __fastcall TListViewPattern::DoCellLClick(TStateBtn *sender)
{
	TStateBtn *pBtn  = (TStateBtn *)sender;

	if( m_pPtInfo!=(TTextureInfo*)pBtn->m_Data ){
		if( m_nPlayIndex!=this->IndSel )
			f_MM_Stop();

		m_pPtInfo = (TTextureInfo *)pBtn->m_Data;

		if( FOnTextureChanged )
			FOnTextureChanged((TObject*)m_pPtInfo);
	}
}
//---------------------------------------------------------------------------
void __fastcall TListViewPattern::DoCellDBClick(TStateBtn *sender)
{
	TTextureInfo *pPtInfo = NULL;

	if( sender ) {
		TStateBtn *pBtn  = (TStateBtn *)sender;
		pPtInfo  = (TTextureInfo*)pBtn->m_Data;
		m_nPlayIndex = pBtn->Index;
	}
	else {
		pPtInfo = m_pPtInfo;
	}

	if( pPtInfo ){
		TPROSTYLE* info = GetStyleInfo( pPtInfo->idLoc, pPtInfo->idStyle );
		if( !info )
			return;

		int stype = pPtInfo->segType,
			sno   = pPtInfo->segNo,
			iChno = -1,
			nStageNum = m_lstStages ? m_lstStages->size() : 1,
			nBarCount = 0,
			iPlayBar = m_iPlayBar,
			iFBar = -1;

		TStage* aStages = new TStage[nStageNum];

		for( int i=0; i<nStageNum; i++ ){
			TStage* pStage = &aStages[i];

			if( m_lstStages ){
				TStage* pTemp = (*m_lstStages)[i];
				memcpy( pStage, pTemp, sizeof(TStage) );

				if( pTemp->aChords ){
					pStage->aChords = new TBarChords[pTemp->nBarNum];
					memcpy( pStage->aChords, pTemp->aChords, sizeof(TBarChords)*pTemp->nBarNum );
				}
			}
			else{
				int seed = time(NULL);
				int barNum = 4;
				if( stype>=SEGTYPE_INTRO ){
					if( info->idLoc==0 ) {
						if( stype==SEGTYPE_INTRO )
							barNum = info->pOrigin->detail.aIntroBars[sno];
						else
							barNum = info->pOrigin->detail.aEndingBars[sno];
					}
					else if( info->idLoc==1 )
						barNum = info->pShare->aIEBars[stype][sno];
					else
						barNum = info->pLocal->aIEBars[stype][sno];
				}

				pStage->nBarNum  = barNum;

				int key = g_iMelodyKey;
				if( key<0 || key>11 )
					key = seed % 12;

				pStage->iSegKey  = key;
				pStage->iSegType = stype;

				char cType = (seed>>1) % 2;
				int iPreset = (seed>>2) % 4;

				aStages->aChords = new TBarChords[barNum];
				for( int j=0; j<barNum; j++ ){
					char chordType = u_arrChordPreset[cType][iPreset][j] % 4;
					char chordKey = u_arrChordPreset[cType][iPreset][j] / 4;

					aStages->aChords[j].iKey[0]
							= aStages->aChords[j].iKey[1]
							= aStages->aChords[j].iKey[2]
							= aStages->aChords[j].iKey[3] = chordKey;
					aStages->aChords[j].iType[0]
							= aStages->aChords[j].iType[1]
							= aStages->aChords[j].iType[2]
							= aStages->aChords[j].iType[3] = chordType;
				}
			}

			if( pStage->iSegType==stype ){
				pStage->nTrkNum = 1;
				pStage->aTracks = new TComposeTrack;

				TComposeTrack* pTrack = pStage->aTracks;

				pTrack->iProg = pPtInfo->prog;
				pTrack->nVol = pPtInfo->vol;

				if( info->idLoc==0 ){
					pTrack->iStyleLoc = 0;
					pTrack->iStyleId = info->idStyle;
					pTrack->iSegNo = sno;
					iChno = pTrack->iChanSpec = pTrack->iChanNo
							= info->pOrigin->detail.tracks[stype][sno][pPtInfo->chNo].no;
				}
				else if( info->idLoc==1 ){
					TSTYLESHARE* pShare = info->pShare;
					TSHARETRACKREF& rRef = pShare->trkRef[stype][sno][pPtInfo->chNo];

					pTrack->iStyleLoc = 0;
					pTrack->iStyleId = rRef.idStyle;
					pTrack->iSegNo = rRef.segNo;
					iChno = pTrack->iChanSpec = pTrack->iChanNo = rRef.chan;
				}
				else{
					TSTYLELOCAL* pLocal = info->pLocal;
					TTRACKREF& rRef = pLocal->trkRef[stype][sno][pPtInfo->chNo];
					pTrack->iStyleLoc = rRef.idLoc;
					pTrack->iStyleId = rRef.idStyle;
					pTrack->iSegNo = rRef.segNo;
					iChno = pTrack->iChanSpec = pTrack->iChanNo = rRef.chan;
				}

				if( iFBar<0 )
					iFBar = nBarCount;
			}

			nBarCount += pStage->nBarNum;
		}

		if( iPlayBar>=0 && iFBar>iPlayBar )
			iPlayBar = iFBar;

		int len = 1000000;
		BYTE* data = new BYTE[len];
		HRESULT ret = f_CM_Compose( &len, data, g_iMelodyTimeSignature, g_nMelodyTempo,
							 nStageNum, aStages, false, NULL, NULL );

		if( ret==0 ){
			f_MM_LoadDemo( data, len );
			char* strFile = m_iFont==0xFF ? NULL : m_iFont<0x80 ? g_lstFonts[m_iFont]->strFileName
													: g_lstVSTi[m_iFont-0x80]->strFileName;
			f_MM_PlayDemo( NULL, iPlayBar, -1, m_iProg, m_iFont, strFile );
		}
		else
			DebugPrint( "Compose error: %d", ret );

		delete[] data;

		SAFE_DELETE_ARRAY(aStages);
	}
}
//---------------------------------------------------------------------------
void __fastcall TListViewPattern::DoIconLClick(TStateBtn *sender)
{
	if(sender->Index==0) {

		TStateBtn *pBtn   = (TStateBtn *)sender;
		TStateBtn *pCell  =  pBtn->m_PAR;
		TTextureInfo *pPtInfo  = (TTextureInfo *)pCell->m_Data;
		pPtInfo->bCollected = !pPtInfo->bCollected;

		TPROSTYLE* info = GetStyleInfo( pPtInfo->idLoc, pPtInfo->idStyle );
		char chan = info->idLoc==0 ?
							info->pOrigin->detail.tracks[pPtInfo->segType][pPtInfo->segNo][pPtInfo->chNo].no
						: info->idLoc==1 ?
							info->pShare->trkRef[pPtInfo->segType][pPtInfo->segNo][pPtInfo->chNo].chan
						: info->pLocal->trkRef[pPtInfo->segType][pPtInfo->segNo][pPtInfo->chNo].chan;

		SetFavorTexture( pPtInfo->idLoc, pPtInfo->idStyle, pPtInfo->segType, pPtInfo->segNo,
																	chan, pPtInfo->bCollected );
	//	InsColSet( pInsRefTmp, pPtInfo->bCollected );

		pBtn->Paint();
	}
}
//---------------------------------------------------------------------------
int  __fastcall TListViewPattern::DoMouseWheel(TObject *Sender)
{
	TListViewBase::DoMouseWheel(Sender);
//	m_Hint->ReleaseHandle();
}
//---------------------------------------------------------------------------
//void __fastcall TListViewPattern::HintTimerProc(System::TObject* Sender)
//{
//	if( m_HintTimer )
//		m_HintTimer->Enabled = false;
//	if( m_Hint && HintStr.Length()>0 ){
//		m_Hint->ShowHintWindow( ClientToScreen(m_ptMove), HintStr );
//	}
//}
//// ---------------------------------------------------------------------------
