// BreakPoint.h: interface for the CBreakPoint class.
//


#pragma once

//#include <afxtempl.h>

enum class BREAKPOINT
{
	ADDRESS = 1,
	MEMORY_ACCESS = 2
};

// флаги доступа к памяти
constexpr uint32_t BP_MEMACCESS_RD = 1;
constexpr uint32_t BP_MEMACCESS_WR = 2;
constexpr uint32_t BP_MEMACCESS_BYTE = 0100000;

class CBreakPoint
{
		BREAKPOINT          m_type;         // тип точки останова
		uint32_t            m_nMemAccess;   // флаги доступа к памяти
		uint32_t            m_nMemConditions;   // Условия срабатывания точки останова (для памяти)
		uint32_t            m_breakedCmdAddr;   // адрес команды, на которой сработала точка останова
		// если старший бит установлен - то в младшем слове - адрес вектора прерывания, вызвавшего срабатывание
		uint16_t            m_breakAddress; // адрес точки останова
		bool                m_bBreaked;     // признак, срабатывания точки останова.
		bool                m_bShowCond;    // флаг показа, где сработало
		bool                m_bEnable;      // вкл-выкл точку останова
	public:
		CBreakPoint();
		CBreakPoint(uint16_t addr, BREAKPOINT type);
		virtual ~CBreakPoint();

		inline bool         IsEnable() const
		{
			return m_bEnable;
		}

		inline void         SetEnabled(const bool bEnable)
		{
			m_bEnable = bEnable;
		}

		inline bool         IsAddress() const
		{
			return (m_type == BREAKPOINT::ADDRESS);
		}

		inline bool         IsMemAccess() const
		{
			return (m_type == BREAKPOINT::MEMORY_ACCESS);
		}

		inline BREAKPOINT   GetType() const
		{
			return m_type;
		}

		inline uint16_t     GetAddress() const
		{
			return m_breakAddress;
		}

		inline uint32_t     GetMemAccess() const
		{
			return m_nMemAccess;
		}

		inline uint32_t     GetMemPC() const
		{
			return m_breakedCmdAddr;
		}

		inline uint32_t     GetMemAccConditions() const
		{
			return m_nMemConditions;
		}

		inline void SetMemAccess(uint32_t a)
		{
			m_nMemAccess = a;
		}

		inline bool         IsBreaked() const
		{
			return m_bBreaked;
		}

		inline bool         IsShow() const
		{
			// функция - костыль, чтобы показать место, какая точка останова сработала.
			// это из-за того, что в том месте, где вызывается функция UnBreak не срабатывает обновление списка
			return m_bShowCond;
		}

		inline void         UnShow()
		{
			m_bShowCond = false; // больше не надо показывать условия срабатывания
		}

		inline void         SetBreakedC(const uint32_t pc)
		{
			m_bBreaked = true;
			m_nMemConditions = 0;
			m_breakedCmdAddr = pc;
		}

		inline void         SetBreakedM(const uint32_t pc, uint32_t cond = 0)
		{
			m_bBreaked = true;
			m_nMemConditions = cond;
			m_breakedCmdAddr = pc;
		}

		inline void         UnBreak()
		{
			m_bBreaked = false;
			m_bShowCond = true; // а условия срабатывания надо показать
		}
};

using CBreakPointList = std::list<CBreakPoint>;

// массив номеров колонок списка
enum BPT_LIST : int
{
	BPTLST_COL_NUMBER = 0,
	BPTLST_COL_ADDR,
	BPTLST_COL_TYPE,
	BPTLST_COL_CONDITIONS,
	BPTLST_COL_STATUS,

};


class CDebugger;

class CBPTListCtrl : public CListCtrl
{
		DECLARE_DYNAMIC(CBPTListCtrl)
		CDebugger          *m_pDebugger;
		// Construction
	public:
		CBPTListCtrl();
		virtual ~CBPTListCtrl() override;

		void                InitView();
		void                OutContent();
		void                Init();
		void                DeleteSelected();
		void                DeleteAll();
		void                SwitchOnOffSelected();
		void                SwitchAll(const bool bState);

		// Generated message map functions
	protected:
		afx_msg void OnSize(UINT nType, int cx, int cy);
		afx_msg void OnSetFocus(CWnd *pOldWnd);
		afx_msg void OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult);
		afx_msg void OnLvnKeydown(NMHDR *pNMHDR, LRESULT *pResult);
		DECLARE_MESSAGE_MAP()
};
