/*
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 "DialogBinaryString.h"
#include "DebuggerCoreInterface.h"
#include "MemoryRegions.h"
#include "Debugger.h"
#include "ByteShiftArray.h"
#include <QVector>

//------------------------------------------------------------------------------
// Name: DialogBinaryString(QWidget *parent)
// Desc: constructor
//------------------------------------------------------------------------------
DialogBinaryString::DialogBinaryString(QWidget *parent) : QDialog(parent) {
	ui.setupUi(this);
	
	ui.progressBar->setValue(0);
	ui.listWidget->clear();
}

//------------------------------------------------------------------------------
// Name: on_btnFind_clicked()
// Desc: find button event handler
//------------------------------------------------------------------------------
void DialogBinaryString::on_btnFind_clicked() {
	if(Debugger::memoryRegions != 0) {
		Debugger::memoryRegions->sync();

		const QByteArray b = ui.binaryString->value();
		
		ui.listWidget->clear();

		const int sz = b.size();
		ByteShiftArray bsa(sz);
				
		
		QVector<MemoryRegions::Region> r = Debugger::memoryRegions->regions();
		QVector<MemoryRegions::Region>::const_iterator it = r.begin();
		
		const float regionPercentStep = 1.0 / static_cast<double>(r.size()) * 100;
		float regionBase = 0.0;
		ui.progressBar->setValue(0);
		while(it != r.end()) {
		
			bsa.clear();
			const BaseTypes::address_t start_address	= it->start;
			const BaseTypes::address_t end_address		= it->end;
			const BaseTypes::address_t howMany			= end_address - start_address;
			BaseTypes::address_t cur_address = start_address;

			while(cur_address != end_address) {
			
				// shift down bytes
				bsa.shl();

				// read in next byte
				uint8_t next_value = 0;
				Debugger::debuggerBase->readBytes(cur_address, &next_value, 1);
				bsa[sz - 1] = next_value;

				// compare values..
				if(std::memcmp(bsa.data(), b.constData(), sz) == 0) {
					ui.listWidget->addItem(QString().sprintf("%08x", cur_address - sz + 1));
				}

				++cur_address;
				
				const BaseTypes::address_t howManyDone	= cur_address - start_address;
				const int percent = static_cast<int>(regionBase + (static_cast<double>(howManyDone) / static_cast<double>(howMany) * regionPercentStep));
				ui.progressBar->setValue(percent);
			}
			++it;
			regionBase += regionPercentStep;
		}
		ui.progressBar->setValue(100);
	}
}

//------------------------------------------------------------------------------
// Name: on_listWidget_itemDoubleClicked(QListWidgetItem *item)
// Desc: follows the found item in the data view
//------------------------------------------------------------------------------
void DialogBinaryString::on_listWidget_itemDoubleClicked(QListWidgetItem *item) {
	bool ok;
	const QString s = item->text();
	const BaseTypes::address_t addr = s.toUInt(&ok, 16);
	if(ok) {
		Debugger::dumpData(addr);
	}
}
