/*
Copyright (C) 2006 Evan Teran
                   eteran@alum.rit.edu

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include "DialogBreakpoints.h"
#include "DebuggerCoreInterface.h"
#include "PluginAPI.h"
#include "SymbolManager.h"
#include "Expression.h"
#include "Core.h"

#include <QHeaderView>
#include <QInputDialog>
#include <QMessageBox>

//------------------------------------------------------------------------------
// Name: DialogBreakpoints(PluginAPI &api, QWidget *parent)
// Desc: 
//------------------------------------------------------------------------------
DialogBreakpoints::DialogBreakpoints(PluginAPI &api, QWidget *parent) : QDialog(parent), m_API(api) {
	ui.setupUi(this);
	ui.tableWidget->verticalHeader()->hide();
	ui.tableWidget->horizontalHeader()->setStretchLastSection(true);
	ui.tableWidget->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
}

//------------------------------------------------------------------------------
// Name: showEvent(QShowEvent *)
// Desc: 
//------------------------------------------------------------------------------
void DialogBreakpoints::showEvent(QShowEvent *) {
	update();
}

//------------------------------------------------------------------------------
// Name: update()
// Desc: 
//------------------------------------------------------------------------------
void DialogBreakpoints::update() {
	DebuggerCoreInterface::BreakpointState bpState;
	m_API.debuggerCore->backupBreakpoints(bpState);

	ui.tableWidget->setSortingEnabled(false);
	ui.tableWidget->setRowCount(0);
	
	QString temp;
	
	foreach(const Breakpoint &bp, bpState) {
		const int row = ui.tableWidget->rowCount();
		ui.tableWidget->insertRow(row);
	
		ui.tableWidget->setItem(row, 0, new QTableWidgetItem(QString("%1").arg(bp.address, EDB_MAX_HEX, 16, QChar('0'))));
				
		QString bytes;

		for(int i = 0; i < bp.originalBytes.size(); ++i) {
			if(i != 0) {
				bytes += ' ';
			}
			bytes += temp.sprintf("%02x", bp.originalBytes[i] & 0xff);
		}
		
		ui.tableWidget->setItem(row, 1, new QTableWidgetItem(bp.condition));
		ui.tableWidget->setItem(row, 2, new QTableWidgetItem(bytes));
		
		if(bp.oneTime()) {
			ui.tableWidget->setItem(row, 3, new QTableWidgetItem(tr("One Time")));
		} else {
			ui.tableWidget->setItem(row, 3, new QTableWidgetItem(tr("Standard")));
		}
		
		const QString symname = m_API.findFunctionSymbol(bp.address, QString(), 0);
		ui.tableWidget->setItem(row, 4, new QTableWidgetItem(symname));
		
		
	}
	ui.tableWidget->setSortingEnabled(true);
}

//------------------------------------------------------------------------------
// Name: on_btnAdd_clicked()
// Desc: 
//------------------------------------------------------------------------------
void DialogBreakpoints::on_btnAdd_clicked() {

	bool ok;
    QString text = QInputDialog::getText(this, tr("Add Breakpoint"), tr("Address:"), QLineEdit::Normal, QString(), &ok);
	
	if (ok && !text.isEmpty()) {
		Expression<edb::address_t> expr(text, m_API.getVariable, 0, m_API.getDWORD, 0);
		ExpressionError err;
		const edb::address_t address = expr.evaluateExpression(ok, err);
		if(ok) {
			m_API.createBreakpoint(address);
			update();

		} else {
			QMessageBox::information(this, tr("Error In Address Expression!"), err.what());
		}
	}
}

//------------------------------------------------------------------------------
// Name: on_btnCondition_clicked()
// Desc: 
//------------------------------------------------------------------------------
void DialogBreakpoints::on_btnCondition_clicked() {
	QList<QTableWidgetItem *> sel = ui.tableWidget->selectedItems();
	if(sel.size() != 0) {
		bool ok;
		const edb::address_t address = edb::core::stringToAddress(sel.begin()[0]->text(), ok);
		if(ok) {
			const QString condition = m_API.debuggerCore->getBreakpointCondition(address);
			const QString text = QInputDialog::getText(this, tr("Set Breakpoint Condition"), tr("Expression:"), QLineEdit::Normal, condition, &ok);
		    if (ok) {
				m_API.debuggerCore->setBreakpointCondition(address, text);
				update();
			}
		}
	}
}

#if 0
//------------------------------------------------------------------------------
// Name: on_btnAddFunction_clicked()
// Desc: 
//------------------------------------------------------------------------------
void DialogBreakpoints::on_btnAddFunction_clicked() {
    bool ok;
    const QString text = QInputDialog::getText(this, tr("Add Breakpoint On Library Function"), tr("Function Name:"), QLineEdit::Normal, QString(), &ok);
	if (ok && !text.isEmpty()) {
		const QList<SymbolManager::Symbol> syms = m_API.symbolManager().symbols();
		foreach(const SymbolManager::Symbol &current, syms) {
			if(current.name_no_prefix == text) {
				m_API.createBreakpoint(current.address);
			}
		}
		update();
	}
}
#endif

//------------------------------------------------------------------------------
// Name: on_btnRemove_clicked()
// Desc: 
//------------------------------------------------------------------------------
void DialogBreakpoints::on_btnRemove_clicked() {
	QList<QTableWidgetItem *> sel = ui.tableWidget->selectedItems();
	foreach(QTableWidgetItem *it, sel) {
		bool ok;
		const edb::address_t address = edb::core::stringToAddress(it->text(), ok);
		if(ok) {
			m_API.removeBreakpoint(address);
		}
		update();
	}
}
