#include "pch.h"

#include "AZBK.h"
#include "BK001001.h"
#include "BKMSTD10.h"
#include "FDDStd326.h"
#include "MemMapView.h"
#include "Platform.h"


constexpr auto COLUMN_WIDTH_PRT = 78;
constexpr auto COLUMN_WIDTH_REG = 38;
constexpr auto COLUMN_WIDTH_MMV = 120;


constexpr auto COLNUM_MEMMAP = 3;
constexpr auto ROWNUM_SMK = 2;
constexpr auto ROWNUM_MEMMAP = 10;



static const std::array<CRegDumpDocPaneDlgViewHelper::ColParam_t, COLNUM_STD> arLSTSMKCols =
{
	{
		{COL_WIDTH | COL_COLOR, COLUMN_WIDTH_PRT, BG_COLOR},
		{COL_WIDTH | COL_EDITABLE, COLUMN_WIDTH, 0},
	}
};

static const std::array<std::array<CRegDumpDocPaneDlgViewHelper::CellParam_t, COLNUM_STD>, ROWNUM_SMK> arSMKRows =
{
	{
		{{ {COL_VALUE | COL_COLOR, IDS_ALTPRO_MODE,  BG_COLOR}, {COL_EDITABLE, 0, 0} }},
		{{ {COL_VALUE | COL_COLOR, IDS_ALTPRO_CODE,  BG_COLOR}, {COL_EDITABLE, 0, 0} }},
	}
};

static const std::array<CRegDumpDocPaneDlgViewHelper::ColParam_t, COLNUM_MEMMAP> arMMAPCols =
{
	{
		{COL_WIDTH | COL_COLOR, COLUMN_WIDTH, BG_COLOR},
		{COL_WIDTH | 0, 86, 0},
		{COL_WIDTH | 0, 112, 0},
	}
};

static const  std::array<std::array<CRegDumpDocPaneDlgViewHelper::CellParam_t, COLNUM_MEMMAP>, ROWNUM_MEMMAP> arMMAPRows =
{
	{
		{{ {            COL_COLOR, 0,                BG_COLOR}, {COL_COLOR, 0, BG_COLOR}, {COL_COLOR, 0, BG_COLOR} }},
		{{ {COL_VALUE | COL_COLOR, IDS_MEMMAP_SEG0,  BG_COLOR}, {0, 0, 0}, {0, 0, 0}                               }},
		{{ {COL_VALUE | COL_COLOR, IDS_MEMMAP_SEG1,  BG_COLOR}, {0, 0, 0}, {0, 0, 0}                               }},
		{{ {COL_VALUE | COL_COLOR, IDS_MEMMAP_SEG2,  BG_COLOR}, {0, 0, 0}, {0, 0, 0}                               }},
		{{ {COL_VALUE | COL_COLOR, IDS_MEMMAP_SEG3,  BG_COLOR}, {0, 0, 0}, {0, 0, 0}                               }},
		{{ {COL_VALUE | COL_COLOR, IDS_MEMMAP_SEG4,  BG_COLOR}, {0, 0, 0}, {0, 0, 0}                               }},
		{{ {COL_VALUE | COL_COLOR, IDS_MEMMAP_SEG5,  BG_COLOR}, {0, 0, 0}, {0, 0, 0}                               }},
		{{ {COL_VALUE | COL_COLOR, IDS_MEMMAP_SEG6,  BG_COLOR}, {0, 0, 0}, {0, 0, 0}                               }},
		{{ {COL_VALUE | COL_COLOR, IDS_MEMMAP_SEG7,  BG_COLOR}, {0, 0, 0}, {0, 0, 0}                               }},
		{{ {COL_VALUE | COL_COLOR, IDS_MEMMAP_SEG8,  BG_COLOR}, {0, 0, 0}, {0, 0, 0}                               }},
	}
};



/////////////////////////////////////////////////////////////////////////////
// CMemMapView
IMPLEMENT_DYNAMIC(CMemMapView, CRegDumpDocPaneDlgViewHelper)

CMemMapView::CMemMapView()
    = default;

CMemMapView::~CMemMapView()
    = default;

void CMemMapView::DoDataExchange(CDataExchange *pDX)
{
	CRegDumpDocPaneDlgViewHelper::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST_MMP_ALTPRO_DATA, m_listAltPro);
	DDX_Control(pDX, IDC_LIST_MMP_MEMMAP, m_listMemMap);
}

BEGIN_MESSAGE_MAP(CMemMapView, CRegDumpDocPaneDlgViewHelper)
	ON_MESSAGE(WM_INITDIALOG, &CMemMapView::HandleInitDialog)
	ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_MMP_ALTPRO_DATA, &CMemMapView::OnLvnItemchangedMdAltProData)

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// обработчики сообщений CMemMapView
LRESULT CMemMapView::HandleInitDialog(WPARAM wp, LPARAM lp)
{
	CRegDumpDocPaneDlgViewHelper::HandleInitDialog(wp, lp);
	// Создадим список карты памяти
	m_vList.emplace_back(ListParam_t{ &m_listMemMap, arMMAPCols, arMMAPRows.data()->data(), COLNUM_MEMMAP, ROWNUM_MEMMAP, IDC_STATIC_MMP_MEMMAPTITLE, true });
	// создание списка режимов AltPro
	m_vList.emplace_back(ListParam_t{ &m_listAltPro, arLSTSMKCols, arSMKRows.data()->data(), COLNUM_STD, ROWNUM_SMK, IDC_STATIC_MMP_SMKREGTITLE, true });
// Оказалось, что в Windows XP и Windows 7 пользовательский интерфейс выглядит по разному,
// и размеры списков различаются. В одной винде больше, в другой - меньше. Поэтому диалоги
// со списками выглядят криво или там, или там, нельзя сделать, чтобы везде было одинаково красиво.
// Из за этого их приходится динамически подгонять по размерам одного элемента списка.
// Ну и заодно и расставлять в окне диалога красиво.
	int nMaxGrpWidth = 0;
	CPoint ptLT{ 0, 0 };

	for (auto &i : m_vList)
	{
		CreateList(i);
		ResizeList(i, ptLT, nMaxGrpWidth);  // и сразу подвинем
		ReArrangeList(i);
	}

	// теперь сделаем группы все одной ширины
	for (auto &i : m_vList)
	{
		if (i.bVisible)
		{
			SetGrpWidth(GetDlgItem(i.nGrpId), nMaxGrpWidth);
		}
	}

	CRect rect;
	//и под конец изменим размеры самого окна
	GetWindowRect(&rect);
	ScreenToClient(&rect);
	rect.bottom = ptLT.y - ::GetSystemMetrics(SM_CYCAPTION) / 2;
	rect.right = ptLT.x + nMaxGrpWidth;
	m_sizeDefault = rect.Size();
	return TRUE; // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

void CMemMapView::RecreateControls()
{
	const uint32_t status = g_Platform.GetPlatformStatus();
	m_vList[1].bVisible = !!(status & CONFPLATFORM_ALTPRO);
	ReArrangeList(m_vList[1]);
	ClearMemMapView();
}

void CMemMapView::DisplayAltProData()
{
	const auto pDbg = g_Platform.GetDebuggerPtr();
	m_listAltPro.SetItemWithModified(pDbg->GetAltProData(LISTALTPRO_L::LINE_MODE), LISTALTPRO_L::LINE_MODE, LSTSTD_COL::VALUE);
	m_listAltPro.SetItemWithModified(pDbg->GetAltProData(LISTALTPRO_L::LINE_CODE), LISTALTPRO_L::LINE_CODE, LSTSTD_COL::VALUE);
}

void CMemMapView::DisplayMemMapView()
{
	if (const auto brd = g_Platform.GetBoardPtr())
	{
		for (int row = 1, segment = 0; row < ROWNUM_MEMMAP - 1; ++row, ++segment)
		{
			m_listMemMap.SetItemWithModifiedASCII(g_arStrMMVData[0][segment].c_str(), row, 1);
		}
	}

	if (const auto mstd = g_Platform.GetMSTDPtr())
	{
		for (int row = 5, segment = 4; row < ROWNUM_MEMMAP - 1; ++row, ++segment)
		{
			m_listMemMap.SetItemWithModifiedASCII(g_arStrMMVData[1][segment].c_str(), row, 2);
		}
	}
	else if (const auto fdd = g_Platform.GetFDDPtr())
	{
		for (int row = 5, segment = 4; row < ROWNUM_MEMMAP; ++row, ++segment)
		{
			m_listMemMap.SetItemWithModifiedASCII(g_arStrMMVData[1][segment].c_str(), row, 2);
		}
	}
	else if (const auto azbk = g_Platform.GetAZBKPtr())
	{
		for (int row = 1, segment = 0; row < ROWNUM_MEMMAP; ++row, ++segment)
		{
			m_listMemMap.SetItemWithModifiedASCII(g_arStrMMVData[1][segment].c_str(), row, 2);
		}
	}
}

void CMemMapView::OnLvnItemchangedMdAltProData(NMHDR *pNMHDR, LRESULT *pResult)
{
	const auto pNMListView = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
	const int nSubItem = pNMListView->iSubItem;

	if (nSubItem == LSTSTD_COL::VALUE)
	{
		const int pos = pNMListView->iItem;
		const auto pStr = reinterpret_cast<CString *>(pNMListView->lParam);

		if (pStr)
		{
			const uint16_t value = Global::OctStringToWord(*pStr);
			g_Platform.GetDebuggerPtr()->SetDebugAltProData(pos, value);
			m_listAltPro.SetItemWithModified(value, pos, nSubItem);
			// Тут надо принудительно обновить содержимое дампера
			GetParentFrame()->PostMessage(WM_MEMDUMP_NEED_UPDATE);
			// и отображение карты памяти
			DisplayMemMapView();
		}
	}

	*pResult = S_OK;
}


void CMemMapView::DisplayRegDump()
{
	if (IsWindowVisible())
	{
		if (g_Platform.GetPlatformStatus() & CONFPLATFORM_ALTPRO)
		{
			DisplayAltProData();
		}

		DisplayMemMapView();
	}
}

void CMemMapView::ClearMemMapView()
{
	for (int i = 0; i < ROWNUM_MEMMAP; ++i)
	{
		m_listMemMap.SetItemWithModifiedASCII(_T(""), i, 1);
		m_listMemMap.SetItemWithModifiedASCII(_T(""), i, 2);
	}

	if (const auto brd = g_Platform.GetBoardPtr())
	{
		m_listMemMap.SetItemWithModifiedASCII(brd->GetBoardName().c_str(), 0, 1);
	}

	if (const auto fdd = g_Platform.GetFDDPtr())
	{
		m_listMemMap.SetItemWithModifiedASCII(fdd->GetBoardName().c_str(), 0, 2);
	}
	else if (const auto mstd = g_Platform.GetMSTDPtr())
	{
		m_listMemMap.SetItemWithModifiedASCII(mstd->GetBoardName().c_str(), 0, 2);
	}
	else if (const auto azbk = g_Platform.GetAZBKPtr())
	{
		m_listMemMap.SetItemWithModifiedASCII(azbk->GetBoardName().c_str(), 0, 2);
	}
}

