/***************************************************************************
                          changelog.cpp  -  description
                             -------------------
    begin                : Sat Feb 14 2003
    copyright            : (C) 2003 by Simone Gotti
    email                : simone.gotti@email.it
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "changelog.h"

#include <kdebug.h>
#include <qregexp.h>

Changelog::Changelog(QByteArray& changelog, SyncAnchor type, QWidget *parent, const char *name)
		: QObject(parent, name), changelog(changelog)
{
	SyncAnchorType = type,

	                 getAllRecords=false;
	mSerialNumber = QString::null;
	mDatabaseId = QString::null;

	changelogStream = new QTextStream( changelog, IO_ReadOnly );

	QString st;
	while ((st = changelogStream->readLine()) != QString::null)
		changelogStrings.push_back(st);

	//Write the changelog
	QStringList::Iterator it;

	kdDebug() << "Changelog Start." << endl;
	for ( it = changelogStrings.begin(); it != changelogStrings.end(); ++it )
		kdDebug() << *it << endl;

	kdDebug() << "Changelog End." << endl;

	getSerialNumber();
	getDatabaseId();
	getChangelogRecords();
	getHardDeletedRecords();

	// Transform in a reduced Changelog
	createReducedChangelog();
}

Changelog::~Changelog() {}

Changelog::record::record()
{
	mIsModified = false;
	mIsDeleted = false;
	mIsHardDeleted = false;
}

Changelog::record::~record() {}


void Changelog::getSerialNumber()
{
	QRegExp rx("^SN:");
	QStringList matchingStrings = changelogStrings.grep(rx);
	QStringList::Iterator it;

	if((it = matchingStrings.begin()) != matchingStrings.end())
		mSerialNumber = (*it).section(rx, 1);
}

void Changelog::getDatabaseId()
{
	QRegExp rx("^DID:");
	QStringList matchingStrings = changelogStrings.grep(rx);
	QStringList::Iterator it;

	if((it = matchingStrings.begin()) != matchingStrings.end())
		mDatabaseId = (*it).section(rx, 1);
}

void Changelog::getChangelogRecords()
{

	QStringList matchingStrings = changelogStrings.grep("*");
	QStringList::Iterator it;

	it = matchingStrings.begin();

	if (it != matchingStrings.end()) {
		// There is a string with an *
		// We have to make a SLOW SYNC!!!
		getAllRecords=true;

	} else {
		getAllRecords=false;
		getModifiedRecords();
		getDeletedRecords();

	}
}

void Changelog::getModifiedRecords()
{
	QRegExp rx("^M:");
	QStringList matchingStrings = changelogStrings.grep(rx);
	QStringList::Iterator it;

	for ( it = matchingStrings.begin(); it != matchingStrings.end(); ++it ) {

		record *curRecord = new record();
		curRecord->mIsModified=true;

		curRecord->mChangeCounter = (*it).section(":", 1,1);
		curRecord->mTimeStamp = (*it).section(":", 2,2);
		curRecord->mLUID = (*it).section(":", 3,3);

		mRecordsList.append(*curRecord);

		kdDebug() << "Found a MODIFIED Record, LUID: " << curRecord->LUID() << endl;
	}
}

void Changelog::getDeletedRecords()
{
	QRegExp rx("^D:");
	QStringList matchingStrings = changelogStrings.grep(rx);
	QStringList::Iterator it;

	for ( it = matchingStrings.begin(); it != matchingStrings.end(); ++it ) {

		record *curRecord = new record();
		curRecord->mIsDeleted=true;

		curRecord->mChangeCounter = (*it).section(":", 1,1);
		curRecord->mTimeStamp = (*it).section(":", 2,2);
		curRecord->mLUID = (*it).section(":", 3,3);

		mRecordsList.append(*curRecord);

		kdDebug() << "Found a DELETED Record, LUID: " << curRecord->LUID() << endl;
	}
}

void Changelog::getHardDeletedRecords()
{
	QRegExp rx("^H:");
	QStringList matchingStrings = changelogStrings.grep(rx);
	QStringList::Iterator it;

	for ( it = matchingStrings.begin(); it != matchingStrings.end(); ++it ) {

		record *curRecord = new record();
		curRecord->mIsHardDeleted=true;

		curRecord->mChangeCounter = (*it).section(":", 1,1);
		curRecord->mTimeStamp = (*it).section(":", 2,2);
		curRecord->mLUID = (*it).section(":", 3,3);

		mRecordsList.append(*curRecord);

		kdDebug() << "Found an HARDDELETED Record, LUID: " << curRecord->LUID() << endl;
	}
}

void Changelog::createReducedChangelog()
{
	kdDebug() << "createReducedChangelog()" << endl;

	QValueList<record>::Iterator it1, it2;
	for ( it1 = mRecordsList.begin(); it1 != mRecordsList.end(); ++it1 ) {
		for ( it2 = mRecordsList.begin(); it2 != mRecordsList.end(); ++it2 ) {
			if(it1 != it2 && (*it2).mLUID == (*it1).mLUID) {
				kdDebug() << "found 2 entries with the same ChangeCounter" << endl;
				if(SyncAnchorType == ChangeCounters) {
					if((*it2).mChangeCounter > (*it1).mChangeCounter) {
						kdDebug() << "Reducing Changelog:      removing: " << (*it1).mLUID << " with CC: " << (*it1).mChangeCounter << endl;
						kdDebug() << "because I've found a newer record: " << (*it2).mLUID << " with CC: " << (*it2).mChangeCounter << endl;
						mRecordsList.remove(it1);
					}
				}
				if(SyncAnchorType == TimeStamps) {
					if((*it2).mChangeCounter > (*it1).mChangeCounter) {
						kdDebug() << "Reducing Changelog:      removing: " << (*it1).mLUID << " with TS: " << (*it1).mChangeCounter << endl;
						kdDebug() << "because I've found a newer record: " << (*it2).mLUID << " with TS: " << (*it2).mChangeCounter << endl;
						mRecordsList.remove(it1);
					}
				}
			}
		}
	}
}

bool Changelog::meta()
{
	return getAllRecords;
}

QString Changelog::serialNumber()
{
	return mSerialNumber;
}

QString Changelog::databaseId()
{
	return mDatabaseId;
}

QValueList<Changelog::record> Changelog::recordsList()
{
	return mRecordsList;
}

QString Changelog::record::changeCounter()
{
	return mChangeCounter;
}

QString Changelog::record::timeStamp()
{
	return mTimeStamp;
}

QString Changelog::record::LUID()
{
	return mLUID;
}

bool Changelog::record::isModified()
{
	return mIsModified;
}

bool Changelog::record::isDeleted()
{
	return mIsDeleted;
}

bool Changelog::record::isHardDeleted()
{
	return mIsHardDeleted;
}


#include "changelog.moc"


