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

#include <vcl.h>
#pragma hdrstop

#include "SetUpFormUnit.h"
#include <mmsystem.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "GeneralDialogPanel"
#pragma link "PNGButton"
#pragma link "LineEdit"
#pragma link "TextButton"
#pragma resource "*.dfm"
TSetUpForm *SetUpForm;
//---------------------------------------------------------------------------

static const COLORREF
			 colLable = RGB(156, 170, 189);

#define SPEED_MIN             50
#define SPEED_MAX		      200
//---------------------------------------------------------------------------
__fastcall TSetUpForm::TSetUpForm(TComponent* Owner)
	: TForm(Owner)
{

}

//---------------------------------------------------------------------------
void __fastcall TSetUpForm::FormCreate(TObject *Sender)
{
	m_pBKGPanel->Font->Size = g_szFont9;
	m_pEDspeed->SetTextFont(g_strTxtFontName, g_szFont9);
	m_pBtnCancel->FontSize = g_szFont9;
	m_pBtnOK->FontSize = g_szFont9;

	m_plbSpeed->Font->Color = colLable;
	m_pLBSpeedMin->Font->Color = colLable;
	m_pLBSpeedMax->Font->Color = colLable;

	m_plbBeat->Font->Color = colLable;
	m_pLBBeat44->Font->Color = colLable;
	m_pLBBeat43->Font->Color = colLable;
	m_pLBBeat42->Font->Color = colLable;
	m_pLBBeat86->Font->Color = colLable;

	/////////////////////////////
	m_pPNGBTPlayTry->Visible = true;
	m_pPNGBTPlaying->Visible = false;


	m_pSpeedUD->Position = g_nMelodyTempo;
	m_pEDspeed->Text	 = IntToStr(g_nMelodyTempo);
	m_btnSpeed->Hint     = L"设置速度\n连续点击鼠标或空格键";
	m_iTS    =  g_iMelodyTimeSignature;
	m_nTempo =  g_nMelodyTempo;

	m_pTBBeat->Max     = 3;
	m_pTBBeat->Min     = 0;
	m_pTBBeat->Position      = g_iMelodyTimeSignature;
	m_pTBBeat->Enabled = g_Theme.Empty();// g_lstRawBars.empty();

	m_pTBSpeed->Max    = 200;
	m_pTBSpeed->Min    = 50;
	m_pTBSpeed->Position = g_nMelodyTempo;

	HRESULT hResult = f_MM_CreateRealTimeMIDIStream( true );
	if (hResult != S_OK) {
		DebugPrint("Create realtime midi stream error.\n");
	}

	SetTransparent( this );
}
//---------------------------------------------------------------------------


void __fastcall TSetUpForm::m_pEDspeedChange(TObject *Sender)
{
	String str = m_pEDspeed->Text;

	int n = str.Length();
	if (n == 0)
		return;

	bool flag = false;
	for (int i = 1; i <= n; i++) {
		if (str[i] < '0' || str[i] > '9') {
			m_pEDspeed->Clear();
			flag = true;
			break;
		}
	}

	if (!flag) {
		int iSpeed = StrToInt(str);
		if ( iSpeed > SPEED_MAX )
			m_pEDspeed->Text = iSpeed = SPEED_MAX;

		if( iSpeed>=SPEED_MIN && iSpeed<=SPEED_MAX ) {
			m_pSpeedUD->Position = iSpeed;
			m_pTBSpeed->Position = iSpeed;

			f_MM_SetTempo( iSpeed );
			m_nTempo = iSpeed;
		}
	}
}
//---------------------------------------------------------------------------

void __fastcall TSetUpForm::PNGBTPlay(TObject *Sender)
{
    TPNGButton *pPlay = (TPNGButton *)Sender;
	if(pPlay == m_pPNGBTPlayTry) {
		f_MM_Stop();
		f_MM_Play( Handle, 0, TYPE_BEAT );

		m_pPNGBTPlayTry->Hide();
		m_pPNGBTPlaying->Show();

	}else if(pPlay == m_pPNGBTPlaying){
		f_MM_Stop();

		m_pPNGBTPlayTry->Show();
		m_pPNGBTPlaying->Hide();
	}
}
//---------------------------------------------------------------------------

void __fastcall TSetUpForm::FormClose(TObject *Sender, TCloseAction &Action)
{
	f_MM_Stop();

	HRESULT hResult = f_MM_FreeRealTimeMIDIStream();
	if (hResult != S_OK) {
		DebugPrint("Free realtime midi stream error.\n");
	}
}
//---------------------------------------------------------------------------

void __fastcall TSetUpForm::m_btnSpeedMouseDown(TObject *Sender, TMouseButton Button,
		  TShiftState Shift, int X, int Y)
{
	if( m_pPNGBTPlaying->Visible ){
		f_MM_Stop();

		m_pPNGBTPlayTry->Show();
		m_pPNGBTPlaying->Hide();
	}

	static int nDownNums = 0;
	static DWORD timeIni = 0;
	static DWORD timeSAverage = 0;
	DWORD timeCur = timeGetTime();
	static DWORD timePre = timeCur;
	DWORD nCalTime;

	HRESULT hRet = f_MM_RealTimeMIDINoteOn( 42 ); //36
	bool bTempo200 = (timeCur-timePre) < (60000/200)?(timeCur-timePre!=0?1:0):0;
	static int i=1;
	i++;
	//如果距离上次时间
	//大于 一拍最慢速度所需时间
	//重置 nDownNums和初始时间
	if( timeCur-timePre > 60000/50 ) {
		nDownNums = 0;
		timeIni   = 0;
	}
	nDownNums++;

	if( nDownNums<=3 ) {
		if( bTempo200 ) {
			nDownNums--;
		}else if(nDownNums != 1){
			timeIni += timeCur - timePre;
		}
	}
	if( nDownNums>=3 && !bTempo200){

		if(nDownNums==3){
			nCalTime = timeSAverage = timeIni/2;
		}else{ //平滑处理
			nCalTime = timeCur - timePre;
			nCalTime = (nCalTime + timeSAverage*3)/4;
			timeSAverage = nCalTime;
		}

		int nTempo = 0;
		if( nCalTime )
			nTempo = 60000/nCalTime;
		if( nTempo>=50 && nTempo<=200 ){
			m_pSpeedUD->Position = nTempo;
			m_pTBSpeed->Position = nTempo;
			m_pEDspeed->Text = IntToStr(nTempo);

			f_MM_SetTempo( nTempo );
			m_nTempo = nTempo;
		}
	}

	timePre = timeCur;
}
//---------------------------------------------------------------------------

void __fastcall TSetUpForm::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift)

{
	switch( Key ){
	case VK_SPACE:
		m_btnSpeedMouseDown( NULL, mbLeft, TShiftState(NULL), 0, 0 );
		m_btnSpeed->SetDown(true);
		break;

	case VK_ESCAPE:
		ModalResult = mrCancel;
		break;

	case VK_RETURN:
		ModalResult = mrOk;
		break;

	default:
		break;
	}
}
//---------------------------------------------------------------------------

void __fastcall TSetUpForm::FormKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)

{
	switch( Key ){
	case VK_SPACE:
//		m_btnSpeedMouseDown( NULL, mbLeft, TShiftState(NULL),0 ,0 );
		m_btnSpeed->SetDown(false);
		break;

	default:
		break;
	}
}
//---------------------------------------------------------------------------

void __fastcall TSetUpForm::SkinTrackBarChange(TObject *Sender)
{
	TSkinTrackBar *pTB = (TSkinTrackBar *)Sender;
	if( pTB == m_pTBSpeed) {
		int iSpeed = pTB->Position;
		m_pSpeedUD->Position = iSpeed;
		m_pEDspeed->Text = IntToStr(iSpeed);

		f_MM_SetTempo( iSpeed );
		m_nTempo = iSpeed;

	}else {
		f_MM_Stop();

		 f_MM_SetTimeSignature( pTB->Position );
		 m_iTS = pTB->Position;

		if( m_pPNGBTPlaying->Visible )
			f_MM_Play( Handle, 0, TYPE_BEAT );
	}
}
//---------------------------------------------------------------------------

void __fastcall TSetUpForm::EventUDOnClicked(TObject *Sender, TUDBtnType Button)
{
	if(Button == btNext)
		m_pSpeedUD->Position += 1;
	else
		m_pSpeedUD->Position -= 1;

	if(m_pSpeedUD->Position > SPEED_MAX)
		m_pSpeedUD->Position = SPEED_MAX;
	else if(m_pSpeedUD->Position < SPEED_MIN)
		m_pSpeedUD->Position = SPEED_MIN;

	m_pTBSpeed->Position = m_pSpeedUD->Position;
	m_pEDspeed->Text = IntToStr(m_pSpeedUD->Position);

	f_MM_SetTempo( m_pSpeedUD->Position );
	m_nTempo = m_pSpeedUD->Position;
}
//---------------------------------------------------------------------------


