#include "StdAfx.h"
#include <utility> //#include <algorithm>
#include "BKSettingsDlg.h"
#include "BK.h"
#include "LoadImgDlg.h"
#include "Config.h"

BEGIN_MESSAGE_MAP(CSettingsDlg, CDialogEx)
	ON_BN_CLICKED(ID_BUTTON_SELECT_HDD0, &CSettingsDlg::OnBnClickedSelect0)
	ON_BN_CLICKED(ID_BUTTON_SELECT_HDD1, &CSettingsDlg::OnBnClickedSelect1)
	ON_BN_CLICKED(ID_BUTTON_EXCHG_HDD, &CSettingsDlg::OnBnClickedExchange)
END_MESSAGE_MAP()


CSettingsDlg::CSettingsDlg() : CDialogEx(CSettingsDlg::IDD)
{
}

void CSettingsDlg::DoDataExchange(CDataExchange *pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BOOL CSettingsDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	GetDlgItem(IDC_EMUL_COMPILED)->SetWindowText(theApp.m_strProgramTitleVersion);
	auto ScreenRenderType = static_cast<CComboBox *>(GetDlgItem(IDC_SETT_COMBO_SCRRENDER));
	CString str;
	str.LoadString(IDS_RENDER_OGL);
	ScreenRenderType->AddString(str.GetString());
	str.LoadString(IDS_RENDER_D2D);
	ScreenRenderType->AddString(str.GetString());
	str.LoadString(IDS_RENDER_DIB);
	ScreenRenderType->AddString(str.GetString());
	str.LoadString(IDS_RENDER_D3D);
	ScreenRenderType->AddString(str.GetString());
	ScreenRenderType->SetCurSel(static_cast<int>(g_Config.m_nScreenRenderType));
	auto OscRenderType = static_cast<CComboBox *>(GetDlgItem(IDC_SETT_COMBO_OSCRENDER));
	str.LoadString(IDS_RENDER_OGL);
	OscRenderType->AddString(str.GetString());
	str.LoadString(IDS_RENDER_D2D);
	OscRenderType->AddString(str.GetString());
	str.LoadString(IDS_RENDER_GDI);
	OscRenderType->AddString(str.GetString());
	OscRenderType->SetCurSel(static_cast<int>(g_Config.m_nOscRenderType));
	auto SoundSampleRate = static_cast<CComboBox *>(GetDlgItem(IDC_SETT_COMBO_SOUNDSR));
	int nNumPos = 0, nPos = 0;

	for (const auto &i : g_EnabledSSR)
	{
		SoundSampleRate->AddString((LPCTSTR)IntToString(i));  // Заберём из массива список для выпадашки

		if (g_Config.m_nSoundSampleRate == i) // Переведём значение в номер позиции в выпадашке
		{
			nNumPos = nPos;
		}

		nPos++;
	}

	SoundSampleRate->SetCurSel(nNumPos);
	auto SoundChipModel = static_cast<CComboBox *>(GetDlgItem(IDC_SETT_COMBO_SNDCHIPMODEL));
	nNumPos = 0, nPos = 0;

	for (const auto &m : g_EnabledSoundChipModels)
	{
		SoundChipModel->AddString(m.strModel);

		if (g_Config.m_nSoundChipModel == m.nModelNum) // Переведём значение в номер позиции в выпадашке
		{
			nNumPos = nPos;
		}

		nPos++;
	}

	SoundChipModel->SetCurSel(nNumPos);
	auto SoundChipFreq = static_cast<CComboBox *>(GetDlgItem(IDC_SETT_COMBO_SNDCHIPFREQ));
	nNumPos = -1, nPos = 0;

	for (const auto &f : g_SoundChipFrequences)
	{
		SoundChipFreq->AddString(f.strFreq);

		if (g_Config.m_nSoundChipFrequency == f.nFreq) // Переведём значение в номер позиции в выпадашке
		{
			nNumPos = nPos;
		}

		nPos++;
	}

	SoundChipFreq->SetCurSel(nNumPos);

	if (nNumPos < 0)
	{
		SetDlgItemText(IDC_SETT_COMBO_SNDCHIPFREQ, (LPCTSTR)IntToString(g_Config.m_nSoundChipFrequency));
	}

	// Model Board
	register CONF_BKMODEL n = g_Config.GetBKModelNumber();
	CString strConfigName = g_mstrConfigBKModelParameters[static_cast<int>(n)].strBKModelName;
	GetDlgItem(IDC_SETT_BOARD)->SetWindowText(strConfigName);
	// HDD Images
	CString strHDDImgName = g_Config.GetHDDriveImgName(static_cast<int>(HDD_MODE::HDD_MASTER));
	GetDlgItem(IDC_SETT_HDD0)->SetWindowText(strHDDImgName);
	m_aHDD[static_cast<int>(HDD_MODE::HDD_MASTER)].Old = strHDDImgName;
	strHDDImgName = g_Config.GetHDDriveImgName(static_cast<int>(HDD_MODE::HDD_SLAVE));
	GetDlgItem(IDC_SETT_HDD1)->SetWindowText(strHDDImgName);
	m_aHDD[static_cast<int>(HDD_MODE::HDD_SLAVE)].Old = strHDDImgName;
	return TRUE;
}

void CSettingsDlg::Save()
{
	//получим новый тип рендера экрана
	auto ScreenRenderType = static_cast<CComboBox *>(GetDlgItem(IDC_SETT_COMBO_SCRRENDER));
	auto nNewRender = static_cast<CONF_SCREEN_RENDER>(ScreenRenderType->GetCurSel());

	if (g_Config.m_nScreenRenderType != nNewRender)  // Если что-то поменялось
	{
		g_Config.m_nScreenRenderType = nNewRender;
	}

	//получим новый тип рендера осциллографа
	auto OscRenderType = static_cast<CComboBox *>(GetDlgItem(IDC_SETT_COMBO_OSCRENDER));
	auto nNewOSC = static_cast<CONF_OSCILLOSCOPE_RENDER>(OscRenderType->GetCurSel());

	if (g_Config.m_nOscRenderType != nNewOSC)        // Если что-то поменялось
	{
		g_Config.m_nOscRenderType = nNewOSC;
	}

	g_Config.CheckRenders();
	//получим новую частоту дискретизации звука
	auto SoundSampleRate = static_cast<CComboBox *>(GetDlgItem(IDC_SETT_COMBO_SOUNDSR));

	if (g_Config.m_nSoundSampleRate != g_EnabledSSR[SoundSampleRate->GetCurSel()])  // Если что-то поменялось
	{
		g_Config.m_nSoundSampleRate = g_EnabledSSR[SoundSampleRate->GetCurSel()];
	}

	//получим новую модель сопра
	auto SoundChipModel = static_cast<CComboBox *>(GetDlgItem(IDC_SETT_COMBO_SNDCHIPMODEL));

	if (g_Config.m_nSoundChipModel != g_EnabledSoundChipModels[SoundChipModel->GetCurSel()].nModelNum)  // Если что-то поменялось
	{
		g_Config.m_nSoundChipModel = g_EnabledSoundChipModels[SoundChipModel->GetCurSel()].nModelNum;
	}

	//получим новую частоту его работы
	CString str;
	GetDlgItemText(IDC_SETT_COMBO_SNDCHIPFREQ, str);
	int freq = _tcstoul(str, nullptr, 10);

	if (freq < 1000000 || freq > 2000000)
	{
		//если это не так - применим частоту по умолчанию.
		freq = DEFAULT_EMU_SOUNDCHIP_FREQUENCY;
	}

	if (g_Config.m_nSoundChipFrequency != freq)  // Если что-то поменялось
	{
		g_Config.m_nSoundChipFrequency = freq;
	}

	// Сохраним остальные исправленные или нет параметры
	CString strHDDImgPath;
	HDDInfo &masterHDD = m_aHDD[static_cast<int>(HDD_MODE::HDD_MASTER)];
	HDDInfo &slaveHDD  = m_aHDD[static_cast<int>(HDD_MODE::HDD_SLAVE)];

	if (masterHDD.Operation == HDDSetOPerate_t::OP_EXCHANGE)    // Обмен
	{
		strHDDImgPath = (masterHDD.New != g_strEmptyUnit) ? masterHDD.New : masterHDD.Old;
	}
	else if (masterHDD.Operation == HDDSetOPerate_t::OP_REPLACE)    // заменили файл
	{
		strHDDImgPath = masterHDD.New;
	}

	if (masterHDD.Operation != HDDSetOPerate_t::OP_NONE /* && strHDDImgPath != masterHDD.Old*/)
	{
		g_Config.SetHDDriveImgName(static_cast<int>(HDD_MODE::HDD_MASTER), strHDDImgPath);
	}

	masterHDD.Operation = HDDSetOPerate_t::OP_NONE;

	if (slaveHDD.Operation == HDDSetOPerate_t::OP_EXCHANGE) // Обмен
	{
		strHDDImgPath = (slaveHDD.New != g_strEmptyUnit) ? slaveHDD.New : slaveHDD.Old;
	}
	else if (slaveHDD.Operation == HDDSetOPerate_t::OP_REPLACE) // заменили файл
	{
		strHDDImgPath = slaveHDD.New;
	}

	if (slaveHDD.Operation != HDDSetOPerate_t::OP_NONE /* && strHDDImgPath != slaveHDD.Old*/)
	{
		g_Config.SetHDDriveImgName(static_cast<int>(HDD_MODE::HDD_SLAVE), strHDDImgPath);
	}

	slaveHDD.Operation = HDDSetOPerate_t::OP_NONE;
}


void CSettingsDlg::OnBnClickedSelect0()
{
	LoadHDDFileImage(static_cast<int>(HDD_MODE::HDD_MASTER));
}
void CSettingsDlg::OnBnClickedSelect1()
{
	LoadHDDFileImage(static_cast<int>(HDD_MODE::HDD_SLAVE));
}

void CSettingsDlg::LoadHDDFileImage(int nDrive)
{
	nDrive &= 1;
	CString strFilterIMG = MAKEINTRESOURCE(IDS_FILEFILTER_BKHDDIMG);
	CLoadImgDlg dlg(true, nullptr, nullptr,
	                OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR | OFN_EXPLORER,
	                strFilterIMG, nullptr);
	dlg.GetOFN().lpstrInitialDir = g_Config.m_strIMGPath; // диалог всегда будем начинать с домашней директории образов.

	if (dlg.DoModal() == IDOK)
	{
		CString str = dlg.GetPathName();
		GetDlgItem(nDrive == static_cast<int>(HDD_MODE::HDD_MASTER) ? IDC_SETT_HDD0 : IDC_SETT_HDD1)->SetWindowText(str);
		m_aHDD[nDrive].New = str;
		m_aHDD[nDrive].Operation = HDDSetOPerate_t::OP_REPLACE;
	}
}

void CSettingsDlg::OnBnClickedExchange()
{
	HDDInfo &masterHDD = m_aHDD[static_cast<int>(HDD_MODE::HDD_MASTER)];
	HDDInfo &slaveHDD = m_aHDD[static_cast<int>(HDD_MODE::HDD_SLAVE)];
	std::swap(masterHDD, slaveHDD);
	masterHDD.Operation = slaveHDD.Operation = HDDSetOPerate_t::OP_EXCHANGE;
	CString strHDDImgPath = (masterHDD.New == g_strEmptyUnit) ? masterHDD.Old : masterHDD.New;
	GetDlgItem(IDC_SETT_HDD0)->SetWindowText(strHDDImgPath);
	strHDDImgPath = (slaveHDD.New == g_strEmptyUnit) ? slaveHDD.Old : slaveHDD.New;
	GetDlgItem(IDC_SETT_HDD1)->SetWindowText(strHDDImgPath);
}


void CSettingsDlg::OnOK()
{
	Save();
	CDialogEx::OnOK();
}

