//******************************************************************************
//
// MIDITrail / MTDashboard
//
// ダッシュボード描画クラス
//
// Copyright (C) 2010-2019 WADA Masashi. All Rights Reserved.
//
//******************************************************************************

#import "YNBaseLib.h"
#import "MTParam.h"
#import "MTConfFile.h"
#import "MTDashboard.h"


//******************************************************************************
// コンストラクタ
//******************************************************************************
MTDashboard::MTDashboard(void)
{
	m_pView = nil;
	m_PosTitleX = 0.0f;
	m_PosTitleY = 0.0f;
	m_PosCounterX = 0.0f;
	m_PosCounterY = 0.0f;
	m_PosFPSX = 0.0f;
	m_PosFPSY = 0.0f;
	m_CounterMag = MTDASHBOARD_DEFAULT_MAGRATE;
	
	m_PlayTimeSec = 0;
	m_TotalPlayTimeSec = 0;
	m_TempoBPM = 0;
	m_BeatNumerator = 0;
	m_BeatDenominator = 0;
	m_BarNo = 0;
	m_BarNum = 0;
	m_NoteCount = 0;
	m_NoteNum = 0;
	m_PlaySpeedRatio = 100;
	m_TempoBPMOnStart = 0;
	m_BeatNumeratorOnStart = 0;
	m_BeatDenominatorOnStart = 0;
	m_FPS = 0.0f;
	
	m_CaptionColor = OGLCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
	
	m_isEnable = true;
	m_isEnableFPS = true;
	m_isiPhone = false;
	m_isEnableLabel = false;
	m_isEnableLabelSpeed = false;
}

//******************************************************************************
// デストラクタ
//******************************************************************************
MTDashboard::~MTDashboard(void)
{
	Release();
}

//******************************************************************************
// ダッシュボード生成
//******************************************************************************
int MTDashboard::Create(
		OGLDevice* pOGLDevice,
		NSString* pSceneName,
		SMSeqData* pSeqData,
		UIView* pView
   )
{
	int result = 0;
	NSString* pTitle = nil;
	SMTrack track;
	SMNoteList noteList;
	char counter[MTDASHBOARD_COUNTER_SIZE];
	char fps[MTDASHBOARD_FPS_SIZE];
	CGRect rect;
	CGFloat height = 0;
	CGFloat width = 0;
	
	Release();
	
	if (pSeqData == NULL) {
		result = YN_SET_ERR(@"Program error.", 0, 0);
		goto EXIT;
	}
	
	m_pView = pView;
	
	//デバイススクリーン情報初期化
	m_DeviceScreenInfo.Initialize();
	
	if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
		m_isiPhone = true;
	}
	
	rect = [[UIScreen mainScreen] bounds];
	height = rect.size.height;
	width = rect.size.width;
	
	//ラベル表示フラグ
	m_isEnableLabel = false;
	m_isEnableLabelSpeed = false;
	if (m_isiPhone) {
		//iPhone 6 以降の画面サイズならラベルを表示する
		if ((height >= 667) || (width >= 667)) {
			m_isEnableLabel = true;
		}
		//iPhone 6 Plus 以上の画面サイズならSPEEDラベルを表示する
		if ((height >= 736) || (width >= 736)) {
			m_isEnableLabelSpeed = true;
		}
	}
	else {
		//iPadの場合はラベルを表示する
		m_isEnableLabel = true;
		m_isEnableLabelSpeed = true;
	}
	
	//設定読み込み
	result = _LoadConfFile(pSceneName);
	if (result != 0) goto EXIT;
	
	//タイトルキャプション
	//pTitle = [NSString stringWithFormat:@"TITLE: %@", pSeqData->GetTitle()];
	pTitle = [NSString stringWithFormat:@"%@", pSeqData->GetTitle()];
	
	//空文字ではテクスチャの生成に失敗するので空白文字に変える
	if ([pTitle length] == 0) {
		pTitle = @" ";
	}
	
	result = m_Title.Create(
					pOGLDevice,
					MTDASHBOARD_FONTNAME,	//フォント名称
					MTDASHBOARD_FONTSIZE,	//フォントサイズ
					pTitle					//キャプション
				);
	if (result != 0) goto EXIT;
	m_Title.SetColor(m_CaptionColor);
	
	//カウンタキャプション
	result = m_Counter.Create(
					pOGLDevice,
					MTDASHBOARD_FONTNAME,		//フォント名称
					MTDASHBOARD_FONTSIZE,		//フォントサイズ
					MTDASHBOARD_COUNTER_CHARS,	//表示文字
					MTDASHBOARD_COUNTER_SIZE	//キャプションサイズ
				);
	if (result != 0) goto EXIT;
	m_Counter.SetColor(m_CaptionColor);
	
	//FPS
	result = m_CounterFPS.Create(
					pOGLDevice,
					MTDASHBOARD_FONTNAME,		//フォント名称
					MTDASHBOARD_FONTSIZE,		//フォントサイズ
					MTDASHBOARD_FPS_CHARS,		//表示文字
					MTDASHBOARD_FPS_SIZE		//キャプションサイズ
				);
	if (result != 0) goto EXIT;
	m_CounterFPS.SetColor(m_CaptionColor);
	
	//全体演奏時間
	SetTotalPlayTimeSec(pSeqData->GetTotalPlayTime()/1000);
	
	//テンポ(BPM)
	SetTempoBPM(pSeqData->GetTempoBPM());
	m_TempoBPMOnStart = pSeqData->GetTempoBPM();
	
	//拍子記号
	SetBeat(pSeqData->GetBeatNumerator(), pSeqData->GetBeatDenominator());
	m_BeatNumeratorOnStart = pSeqData->GetBeatNumerator();
	m_BeatDenominatorOnStart = pSeqData->GetBeatDenominator();
	
	//小節番号
	SetBarNo(1);
	
	//小節数
	SetBarNum(pSeqData->GetBarNum());
	
	result = pSeqData->GetMergedTrack(&track);
	if (result != 0) goto EXIT;
	
	result = track.GetNoteList(&noteList);
	if (result != 0) goto EXIT;
	
	m_NoteNum = noteList.GetSize();
	
	//カウンタ表示文字列生成
	result = _GetCounterStr(counter, MTDASHBOARD_COUNTER_SIZE);
	if (result != 0) goto EXIT;
	
	result = m_Counter.SetString(counter);
	if (result != 0) goto EXIT;
	
	//カウンタ表示位置を算出
	result = _GetCounterPos(&m_PosCounterX, &m_PosCounterY);
	if (result != 0) goto EXIT;
	
	//タイトル表示位置
	m_PosTitleX = m_PosCounterX;
	m_PosTitleY = MTDASHBOARD_FRAMESIZE + m_DeviceScreenInfo.GetMargin_LandscapeTop();
	
	//FPS表示文字列生成
	result = _GetFPSStr(fps, MTDASHBOARD_FPS_SIZE);
	if (result != 0) goto EXIT;
	
	result = m_CounterFPS.SetString(fps);
	if (result != 0) goto EXIT;
	
	//FPS表示位置
	result = _GetCounterFPSPos(&m_PosFPSX, &m_PosFPSY);
	if (result != 0) goto EXIT;
	
EXIT:;
	return result;
}

//******************************************************************************
// 移動
//******************************************************************************
int MTDashboard::Transform(
		OGLDevice* pOGLDevice,
		OGLVECTOR3 camVector
	)
{
	int result = 0;
	return result;
}

//******************************************************************************
// 描画
//******************************************************************************
int MTDashboard::Draw(
		OGLDevice* pOGLDevice
	)
{
	int result = 0;
	char counter[MTDASHBOARD_COUNTER_SIZE];
	char fps[MTDASHBOARD_FPS_SIZE];
	
	if (pOGLDevice == NULL) {
		result = YN_SET_ERR(@"Program error.", 0, 0);
		goto EXIT;
	}
	
	//タイトルとカウンタ文字列描画
	if (m_isEnable) {
		//タイトル描画：カウンタと同じ拡大率で表示する
		result = m_Title.Draw(pOGLDevice, m_PosTitleX, m_PosTitleY, m_CounterMag);
		if (result != 0) goto EXIT;
		
		result = _GetCounterStr(counter, MTDASHBOARD_COUNTER_SIZE);
		if (result != 0) goto EXIT;
		
		result = m_Counter.SetString(counter);
		if (result != 0) goto EXIT;
		
		result = m_Counter.Draw(pOGLDevice, m_PosCounterX, m_PosCounterY, m_CounterMag);
		if (result != 0) goto EXIT;
	}
	
	//FPS文字列描画
	if (m_isEnableFPS) {
		result = _GetFPSStr(fps, MTDASHBOARD_FPS_SIZE);
		if (result != 0) goto EXIT;
		
		result = m_CounterFPS.SetString(fps);
		if (result != 0) goto EXIT;
		
		result = m_CounterFPS.Draw(pOGLDevice, m_PosFPSX, m_PosFPSY, m_CounterMag);
		if (result != 0) goto EXIT;
	}
	
EXIT:;
	return result;
}

//******************************************************************************
// 解放
//******************************************************************************
void MTDashboard::Release()
{
	m_Title.Release();
	m_Counter.Release();
}

//******************************************************************************
// カウンタ表示位置取得
//******************************************************************************
int MTDashboard::_GetCounterPos(
		float* pX,
		float* pY
	)
{
	int result = 0;
	CGRect rect;
	unsigned int cw, ch = 0;
	unsigned int tw, th = 0;
	unsigned int charHeight, charWidth = 0;
	unsigned int captionWidth = 0;
	//float newMag = 0.0;
	
	//クライアント領域のサイズを取得
	rect = [m_pView bounds];
	cw = rect.size.width;
	ch = rect.size.height;
	
	//テクスチャサイズ取得
	m_Counter.GetTextureSize(&th, &tw);
	
	//文字サイズ
	charHeight = th;
	charWidth = tw / strlen(MTDASHBOARD_COUNTER_CHARS);
	
	//拡大率1.0のキャプションサイズ
	captionWidth = charWidth * MTDASHBOARD_COUNTER_SIZE;
	
	//カウンタ文字列が画面からはみ出す場合は画面に収まるように拡大率を更新する
	//  タイトルがはみ出すのは気にしないことにする
	//if (((cw - (MTDASHBOARD_FRAMESIZE*2)) < captionWidth) && (tw > 0)) {
	//	newMag = (float)(cw - (MTDASHBOARD_FRAMESIZE*2)) / (float)captionWidth;
	//	if (m_CounterMag > newMag) {
	//		m_CounterMag = newMag;
	//	}
	//}
	
	//テクスチャの表示倍率を考慮して表示位置を算出
	*pX = MTDASHBOARD_FRAMESIZE;
	*pY = (float)ch - ((float)th * m_CounterMag) - MTDASHBOARD_FRAMESIZE;
	
	//セーフエリア内に表示位置を移動
	if (m_DeviceScreenInfo.IsEnableSafeArea()) {
		*pX += m_DeviceScreenInfo.GetMargin_LandscapeLeft() + m_DeviceScreenInfo.GetMargin_RoundedCorner();
		*pY -= m_DeviceScreenInfo.GetMargin_LandscapeBottom();
	}
	
EXIT:;
	return result;
}

//******************************************************************************
// FPS表示位置取得
//******************************************************************************
int MTDashboard::_GetCounterFPSPos(
		float* pX,
		float* pY
	)
{
	int result = 0;
	CGRect rect;
	unsigned int cw, ch = 0;
	unsigned int tw, th = 0;
	unsigned int charHeight, charWidth = 0;
	
	//クライアント領域のサイズを取得
	rect = [m_pView bounds];
	cw = rect.size.width;
	ch = rect.size.height;
	
	//テクスチャサイズ取得
	m_CounterFPS.GetTextureSize(&th, &tw);
	
	//文字サイズ
	charHeight = th;
	charWidth = tw / strlen(MTDASHBOARD_FPS_CHARS);
	
	//テクスチャの表示倍率を考慮して表示位置を算出：画面右上 "FPS:000.0" 9文字
	*pX = (float)cw - MTDASHBOARD_FRAMESIZE - ((float)charWidth * m_CounterMag * 9);
	*pY = MTDASHBOARD_FRAMESIZE;
	
	//セーフエリア内に表示位置を移動
	if (m_DeviceScreenInfo.IsEnableSafeArea()) {
		*pX -= m_DeviceScreenInfo.GetMargin_LandscapeRight() + m_DeviceScreenInfo.GetMargin_RoundedCorner();
		*pY += m_DeviceScreenInfo.GetMargin_LandscapeTop();
	}
	
EXIT:;
	return result;
}

//******************************************************************************
// 演奏時間登録（秒）
//******************************************************************************
void MTDashboard::SetPlayTimeSec(
		unsigned int playTimeSec
	)
{
	m_PlayTimeSec = playTimeSec;
}

//******************************************************************************
// 全体演奏時間登録（秒）
//******************************************************************************
void MTDashboard::SetTotalPlayTimeSec(
		unsigned int totalPlayTimeSec
	)
{
	m_TotalPlayTimeSec = totalPlayTimeSec;
}

//******************************************************************************
// テンポ登録(BPM)
//******************************************************************************
void MTDashboard::SetTempoBPM(
		unsigned int bpm
	)
{
	m_TempoBPM = bpm;
}

//******************************************************************************
// 拍子記号登録
//******************************************************************************
void MTDashboard::SetBeat(
		unsigned int numerator,
		unsigned int denominator
	)
{
	m_BeatNumerator = numerator;
	m_BeatDenominator = denominator;
}

//******************************************************************************
// 小節数登録
//******************************************************************************
void MTDashboard::SetBarNum(
		unsigned int barNum
	)
{
	m_BarNum = barNum;
}

//******************************************************************************
// 小節番号登録
//******************************************************************************
void MTDashboard::SetBarNo(
		unsigned int barNo
	)
{
	m_BarNo = barNo;
}

//******************************************************************************
// ノートON登録
//******************************************************************************
void MTDashboard::SetNoteOn()
{
	m_NoteCount++;
}

//******************************************************************************
// 演奏速度登録
//******************************************************************************
void MTDashboard::SetPlaySpeedRatio(
		unsigned int ratio
	)
{
	m_PlaySpeedRatio = ratio;
}

//******************************************************************************
// ノート数登録
//******************************************************************************
void MTDashboard::SetNotesCount(
		unsigned int notesCount
	)
{
	m_NoteCount = notesCount;
}

//******************************************************************************
// FPS登録
//******************************************************************************
void MTDashboard::SetFPS(
		float fps
	)
{
	m_FPS = fps;
}

//******************************************************************************
// カウンタ文字列取得
//******************************************************************************
int MTDashboard::_GetCounterStr(
		char* pStr,
		unsigned int bufSize
	)
{
	int result = 0;
	int eresult = 0;
	char spdstr[16] = {0};
	const char* pCounterFormat = NULL;
	const char* pSpeedFormat = NULL;
	
	//カウンタフォーマット
	if (m_isEnableLabel) {
		//ラベルあり（iPhone 6 以降または iPad）
		pCounterFormat = "TIME:%02u:%02u/%02u:%02u BPM:%03u BEAT:%u/%u BAR:%03u/%03u NOTES:%05u/%05u";
	}
	else {
		//ラベルなし（iPhone 5 以前）
		pCounterFormat = "%02u:%02u/%02u:%02u %03u %u/%u %03u/%03u %05u/%05u";
	}
	
	//SPEEDラベル
	if (m_isEnableLabelSpeed) {
		//ラベルあり（iPhone 6 Plus 以上の画面サイズまたはiPad）
		pSpeedFormat   = " SPEED:%03u%%";
	}
	else {
		//ラベルなし（iPhone 6 Plus 未満の画面サイズ）
		pSpeedFormat   = " %03u%%";
	}
	
	eresult = snprintf(
				pStr,
				bufSize,
				pCounterFormat,
				m_PlayTimeSec / 60,
				m_PlayTimeSec % 60,
				m_TotalPlayTimeSec / 60,
				m_TotalPlayTimeSec % 60,
				m_TempoBPM,
				m_BeatNumerator,
				m_BeatDenominator,
				m_BarNo,
				m_BarNum,
				m_NoteCount,
				m_NoteNum
			);
	if (eresult < 0) {
		result = YN_SET_ERR(@"Program error.", 0, 0);
		goto EXIT;
	}
	
	//演奏速度が100%以外の場合に限りカウンタに表示する
	if (m_PlaySpeedRatio != 100) {
		eresult = snprintf(spdstr, 16, pSpeedFormat, m_PlaySpeedRatio);
		if (eresult < 0) {
			result = YN_SET_ERR(@"Program error.", 0, 0);
			goto EXIT;
		}
		strncat(pStr, spdstr, bufSize - strlen(pStr) - 1);
	}
	
EXIT:;
	return result;
}

//******************************************************************************
// FPS文字列取得
//******************************************************************************
int MTDashboard::_GetFPSStr(
		char* pStr,
		unsigned int bufSize
	)
{
	int result = 0;
	int eresult = 0;
	const char* pFPSFormat = NULL;
	
	//FPSフォーマット
	pFPSFormat = "FPS:%.1f";
	
	eresult = snprintf(
				pStr,
				bufSize,
				pFPSFormat,
				m_FPS
			);
	if (eresult < 0) {
		result = YN_SET_ERR(@"Program error.", 0, 0);
		goto EXIT;
	}
	
EXIT:;
	return result;
}

//******************************************************************************
// リセット
//******************************************************************************
void MTDashboard::Reset()
{
	m_PlayTimeSec = 0;
	m_TempoBPM = m_TempoBPMOnStart;
	m_BeatNumerator = m_BeatNumeratorOnStart;
	m_BeatDenominator = m_BeatDenominatorOnStart;
	m_BarNo = 1;
	m_NoteCount = 0;
}

//******************************************************************************
// 設定ファイル読み込み
//******************************************************************************
int MTDashboard::_LoadConfFile(
		NSString* pSceneName
	)
{
	int result = 0;
	NSString* pHexColor = nil;
	MTConfFile confFile;
	
	result = confFile.Initialize(pSceneName);
	if (result != 0) goto EXIT;
	
	//----------------------------------
	//色情報
	//----------------------------------
	result = confFile.SetCurSection(@"Color");
	if (result != 0) goto EXIT;
	
	//キャプションカラー
	result = confFile.GetStr(@"CaptionRGBA", &pHexColor, @"FFFFFFFF");
	if (result != 0) goto EXIT;
	m_CaptionColor = OGLColorUtil::MakeColorFromHexRGBA(pHexColor);
	
EXIT:;
	return result;
}

//******************************************************************************
// 演奏時間取得
//******************************************************************************
unsigned int MTDashboard::GetPlayTimeSec()
{
	return m_PlayTimeSec;
}

//******************************************************************************
// カウンタ表示設定
//******************************************************************************
void MTDashboard::SetEnable(
		bool isEnable
	)
{
	m_isEnable = isEnable;
}

//******************************************************************************
// FPS表示設定
//******************************************************************************
void MTDashboard::SetEnableFPS(
		bool isEnable
	)
{
	m_isEnableFPS = isEnable;
}

