/*  PCSX2 - PS2 Emulator for PCs
 *  Copyright (C) 2002-2014  PCSX2 Dev Team
 *
 *  PCSX2 is free software: you can redistribute it and/or modify it under the terms
 *  of the GNU Lesser General Public License as published by the Free Software Found-
 *  ation, either version 3 of the License, or (at your option) any later version.
 *
 *  PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 *  PURPOSE.  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along with PCSX2.
 *  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once
#include <wx/listctrl.h>
#include "DebugTools/DebugInterface.h"
#include "DebugTools/Breakpoints.h"
#include "DebugTools/BiosDebugData.h"
#include "DebugTools/MipsStackWalk.h"
#include "CtrlDisassemblyView.h"

struct GenericListViewColumn
{
	const wchar_t *name;
	float size;
	int flags;
};

class GenericListView: public wxListView
{
public:
	GenericListView(wxWindow* parent, GenericListViewColumn* columns, int columnCount);
	void update();

	DECLARE_EVENT_TABLE()
protected:
	void sizeEvent(wxSizeEvent& evt);
	void keydownEvent(wxKeyEvent& evt);
	void postEvent(wxEventType type, int value);
	void mouseEvent(wxMouseEvent& evt);
	void listEvent(wxListEvent& evt);

	virtual wxString getColumnText(int row, int col) const = 0;
	virtual int getRowCount() = 0;
	virtual void onDoubleClick(int itemIndex, const wxPoint& point) { };
	virtual void onRightClick(int itemIndex, const wxPoint& point) { };
	virtual void onKeyDown(int key) { };

	// This flag prevents resizing loop in the resizeColumn method of this class
	// when the Windows Classic theme with some large resolutions around larger
	// than 1024 x 768 have been chosen.
	//
	// The resizing loop will occur by the ListView_SetColumnWidth macro in the
	// Windows SDK called by the wxListCtrl::SetColumnWidth method when the
	// conditions above have been chosen.
	bool m_isInResizeColumn;

private:
	void insertColumns(GenericListViewColumn* columns, int count);
	void resizeColumn(int col, int width);
	void resizeColumns(int totalWidth);
	wxString OnGetItemText(long item, long col) const;

	GenericListViewColumn* columns;
	wxPoint clickPos;
};

class BreakpointList: public GenericListView
{
public:
	BreakpointList(wxWindow* parent, DebugInterface* _cpu, CtrlDisassemblyView* _disassembly);
	void reloadBreakpoints();
protected:
	void onPopupClick(wxCommandEvent& evt);
	
	virtual wxString getColumnText(int row, int col) const;
	virtual int getRowCount();
	virtual void onDoubleClick(int itemIndex, const wxPoint& point);
	virtual void onRightClick(int itemIndex, const wxPoint& point);
	virtual void onKeyDown(int key);
private:
	int getBreakpointIndex(int itemIndex, bool& isMemory) const;
	int getTotalBreakpointCount();
	void editBreakpoint(int itemIndex);
	void toggleEnabled(int itemIndex);
	void gotoBreakpointAddress(int itemIndex);
	void removeBreakpoint(int itemIndex);
	void showMenu(const wxPoint& pos);

	std::vector<BreakPoint> displayedBreakPoints_;
	std::vector<MemCheck> displayedMemChecks_;
	DebugInterface* cpu;
	CtrlDisassemblyView* disasm;
};

class ThreadList: public GenericListView
{
public:
	ThreadList(wxWindow* parent, DebugInterface* _cpu);
	void reloadThreads();
	EEThread getRunningThread();
protected:
	void onPopupClick(wxCommandEvent& evt);
	
	virtual wxString getColumnText(int row, int col) const;
	virtual int getRowCount();
	virtual void onDoubleClick(int itemIndex, const wxPoint& point);
private:
	DebugInterface* cpu;
	std::vector<EEThread> threads;
};

class StackFramesList: public GenericListView
{
public:
	StackFramesList(wxWindow* parent, DebugInterface* _cpu,  CtrlDisassemblyView* _disassembly);
	void loadStackFrames(EEThread& currentThread);
protected:
	void onPopupClick(wxCommandEvent& evt);
	
	virtual wxString getColumnText(int row, int col) const;
	virtual int getRowCount();
	virtual void onDoubleClick(int itemIndex, const wxPoint& point);
private:
	DebugInterface* cpu;
	CtrlDisassemblyView* disassembly;
	std::vector<MipsStackWalk::StackFrame> frames;
};
