/*
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 "DialogStrings.h"
#include "DebuggerCoreInterface.h"
#include "PluginAPI.h"
#include "MemoryRegions.h"
#include "Util.h"
#include "Configuration.h"

#include <QHeaderView>
#include <QMessageBox>
#include <QSortFilterProxyModel>

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
DialogStrings::DialogStrings(PluginAPI &api, QWidget *parent) : QDialog(parent), m_API(api) {
	ui.setupUi(this);
	ui.tableView->verticalHeader()->hide();
	ui.tableView->horizontalHeader()->setStretchLastSection(true);
	ui.tableView->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
	
	m_FilterModel = new QSortFilterProxyModel(this);
	connect(ui.txtSearch, SIGNAL(textChanged(const QString &)), m_FilterModel, SLOT(setFilterFixedString(const QString &)));
}

//------------------------------------------------------------------------------
// Name: on_listWidget_itemDoubleClicked(QListWidgetItem *item)
// Desc: follows the found item in the data view
//------------------------------------------------------------------------------
void DialogStrings::on_listWidget_itemDoubleClicked(QListWidgetItem *item) {	
	bool ok;
	const edb::address_t addr = item->data(Qt::UserRole).toULongLong(&ok);
	if(ok) {
		m_API.dumpData(addr, false);
	}
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogStrings::showEvent(QShowEvent *) {
	m_FilterModel->setFilterKeyColumn(3);
	m_FilterModel->setSourceModel(&m_API.memoryRegions());
	ui.tableView->setModel(m_FilterModel);
	
	ui.progressBar->setValue(0);
	ui.listWidget->clear();
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogStrings::doFind() {

	const int minStringLength = m_API.config().minStringLength;
	
	const QItemSelectionModel *const selModel = ui.tableView->selectionModel();
	const QModelIndexList sel = selModel->selectedRows();
	
	QString str;

	if(sel.size() == 0) {
		QMessageBox::information(this, tr("No Region Selected"), tr("You must select a region which is to be scanned for strings."));
	}

	foreach(const QModelIndex &selected_item, sel) {

		const QModelIndex index = m_FilterModel->mapToSource(selected_item);
		const MemRegion *const region = reinterpret_cast<const MemRegion *>(index.internalPointer());
		
		if(region != 0) {

			edb::address_t start_address		= region->start;
			const edb::address_t end_address	= region->end;
			const edb::address_t orig_start		= start_address;
			
			// do the search for this region!
			while(start_address < end_address) {

				int stringLen = 0;		
				const bool ok = m_API.getASCIIStringAtAddress(start_address, str, minStringLength, 256, stringLen);
				if(ok) {
					QListWidgetItem *const item = new QListWidgetItem(QString("%1: %2").arg(start_address, EDB_MAX_HEX, 16, QChar('0')).arg(str));
					item->setData(Qt::UserRole, start_address);
					ui.listWidget->addItem(item);
				}

				ui.progressBar->setValue(CalculatePercentage((start_address - orig_start), region->size()));

				if(ok) {				
					start_address += stringLen;
				} else {
					++start_address;
				}
			}
		}
	}
}

//------------------------------------------------------------------------------
// Name: on_btnFind_clicked()
// Desc: 
//------------------------------------------------------------------------------
void DialogStrings::on_btnFind_clicked() {
	ui.btnFind->setEnabled(false);
	ui.listWidget->clear();
	ui.progressBar->setValue(0);
	doFind();
	ui.progressBar->setValue(100);
	ui.btnFind->setEnabled(true);
}
