/*
Copyright (C) 2006 - 2009 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 "Debugger.h"
#include "SymbolManager.h"
#include "Expression.h"
#include "Debugger.h"

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

//------------------------------------------------------------------------------
// Name: DialogBreakpoints(QWidget *parent)
// Desc: 
//------------------------------------------------------------------------------
DialogBreakpoints::DialogBreakpoints(QWidget *parent) : QDialog(parent) {
	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 *) {
	updateList();
}

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


	ui.tableWidget->setSortingEnabled(false);
	ui.tableWidget->setRowCount(0);

	const DebuggerCoreInterface::BreakpointState bpState = edb::v1::debuggerBase->backupBreakpoints();
	
	Q_FOREACH(const QSharedPointer<Breakpoint> &bp, bpState) {
		const int row = ui.tableWidget->rowCount();
		ui.tableWidget->insertRow(row);
		
		if(!bp->internal()) {
		
			const edb::address_t address	= bp->address();
			const QString condition			= bp->condition;
			const QByteArray orig_bytes		= bp->originalBytes();
			const bool onetime				= bp->oneTime();
			const QString symname			= edb::v1::findFunctionSymbol(address, QString(), 0);
			const QString bytes				= edb::v1::formatBytes(orig_bytes);

			ui.tableWidget->setItem(row, 0, new QTableWidgetItem(edb::v1::formatPointer(address)));
			ui.tableWidget->setItem(row, 1, new QTableWidgetItem(condition));	
			ui.tableWidget->setItem(row, 2, new QTableWidgetItem(bytes));
			ui.tableWidget->setItem(row, 3, new QTableWidgetItem(onetime ? tr("One Time") : tr("Standard")));
			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, edb::v1::getVariable, 0, edb::v1::getDWORD, 0);
		ExpressionError err;
		const edb::address_t address = expr.evaluateExpression(ok, err);
		if(ok) {
			edb::v1::createBreakpoint(address);
			updateList();

		} 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::v1::stringToAddress(sel.begin()[0]->text(), ok);
		if(ok) {
			const QString condition = edb::v1::debuggerBase->getBreakpointCondition(address);
			const QString text = QInputDialog::getText(this, tr("Set Breakpoint Condition"), tr("Expression:"), QLineEdit::Normal, condition, &ok);
		    if (ok) {
				edb::v1::debuggerBase->setBreakpointCondition(address, text);
				updateList();
			}
		}
	}
}

#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 = edb::v1::symbolManager().symbols();
		Q_FOREACH(const SymbolManager::Symbol &current, syms) {
			if(current.name_no_prefix == text) {
				edb::v1::createBreakpoint(current.address);
			}
		}
		updateList();
	}
}
#endif

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