/*
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 "Debugger.h"
#include "SymbolManager.h"
#include "Expression.h"

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

//------------------------------------------------------------------------------
// Name: 
// 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: 
// Desc: 
//------------------------------------------------------------------------------
void DialogBreakpoints::showEvent(QShowEvent *) {
	update();
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogBreakpoints::update() {
	DebuggerCoreInterface::BreakpointState bpState;
	edb::v1::debuggerBase->backupBreakpoints(bpState);

	ui.tableWidget->setSortingEnabled(false);
	ui.tableWidget->setRowCount(0);
	
	QString temp;
	
	foreach(Breakpoint bp, bpState) {
		const int row = ui.tableWidget->rowCount();
		ui.tableWidget->insertRow(row);
	
		ui.tableWidget->setItem(row, 0, new QTableWidgetItem(temp.sprintf(EDB_FMT_PTR, bp.address)));
				
		QString bytes;

		for(int k = 0; k < bp.originalBytes.size(); ++k) {
			bytes += temp.sprintf("%02x", bp.originalBytes[k] & 0xff);
			if(k != bp.originalBytes.size() - 1) {
				bytes += ' ';
			}
		}
		
		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("One Time"));
		} else {
			ui.tableWidget->setItem(row, 3, new QTableWidgetItem("Standard"));
		}
		
		const QString symname = edb::v1::findFunctionSymbol(bp.address, QString());
		ui.tableWidget->setItem(row, 4, new QTableWidgetItem(symname));
		
		
	}
	ui.tableWidget->setSortingEnabled(true);
}

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

	bool ok;
    QString text = QInputDialog::getText(this, "Add Breakpoint", "Address:", QLineEdit::Normal, QString(), &ok);
	
	if (ok && !text.isEmpty()) {
		Expression<edb::address_t> expr(text, &edb::v1::getVariable, 0, &edb::v1::getDWORD, 0);
		try {
			const edb::address_t address = expr.evaluateExpression();
			edb::v1::createBreakpoint(address);
			update();
		} catch(const Error &err) {
			QMessageBox::information(this, "Error In Address Expression!", err.what());
		}
	}
}

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

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

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogBreakpoints::on_btnRemove_clicked() {
	QList<QTableWidgetItem *> sel = ui.tableWidget->selectedItems();
	if(sel.size() != 0) {
		bool ok;
		const edb::address_t address = sel.begin()[0]->text().toULong(&ok, 16);
		if(ok) {
			edb::v1::removeBreakpoint(address);
		}
		update();
	}
}
