// data.cpp: implementation of the transaction, data, EquiClass
// classes.
//////////////////////////////////////////////////////////////////////

//#include "data.h"
#include "common.h"
//#include "tree.h"
//#include "hash_table.h"
#include "ec_storage.h"
#include "fk_tree.h"
#include <algorithm>
#include <math.h>
#include <iostream>
using namespace std;

////////////////////////////////////////////////
//	external variables & functions
////////////////////////////////////////////////

//extern hash_table *patternTable;
//extern closeHashTable *patternTable;
extern ec_storage *ECstorage;

////////////////////////////////////////////////
//	Transaction class functions
////////////////////////////////////////////////

////////// public functions ////////////////////

void Transaction::DoubleTrans(int item)
{
	int* temp = new int[2*item];
	maxlength = 2*item;
	for(int i=0; i<length; i++)
		temp[i] = t[i];
	delete []t;
	t = temp;
}

////////////////////////////////////////////////
//	Data class functions
////////////////////////////////////////////////

////////// public functions ////////////////////

Data::Data(char *filename)
{
#ifndef BINARY
  //in = fopen(filename,"rt");
	fopen_s(&in, filename, "rt");
#else
  in = fopen(filename, "rb");
#endif
	ts =  NULL;
}

Data::~Data()
{
  if(in) fclose(in);
}

int Data::isOpen()
{
  if(in) return 1;
  else return 0;
}

void Data::removeTS()
{
	tranStore* current = ts, *temp;

	while(current)
	{
		if(current->t)
			delete []current->t;

		temp = current;
		current = current->next;
		delete temp;
	}
}

Transaction *Data::getNextTransaction(Transaction* Trans, bool bltranStore)
{
	int i,j;
	Trans->length = 0;

  // read list of items
#ifndef BINARY	  
	char c;
	int item, pos;
	do {
		item=0;
		pos=0;
		c = getc(in);
		while((c >= '0') && (c <= '9')) {
			item *=10;
			item += int(c)-int('0');
			c = getc(in);
			pos++;
		}
		if(pos)
		{
			if(Trans->length >= Trans->maxlength)
				Trans->DoubleTrans(Trans->length);

			Trans->t[Trans->length] = item;
			Trans->length++;
		}
	}while(c != '\n' && !feof(in));
	// if end of file is reached, rewind to beginning for next pass
	if(feof(in)){
		rewind(in);

		//debug for memory leak 21/10/2004
		delete Trans;
		Trans = NULL;

		return 0;
	}
	// Note, also last transaction must end with newline, 
	// else, it will be ignored
#else
	int i, nitem, *buffer=new int;
	fread((char*)buffer, sizeof(int), 1, in);
	if(feof(in))
	{
	    rewind(in);
		
		//debug for memory leak 21/10/2004
		delete Trans;
		Trans = NULL;

		return 0;
	}
	fread((char*)buffer, sizeof(int), 1, in);
	fread((char*)buffer, sizeof(int), 1, in);
	nitem=*buffer;
	for(i=0; i<nitem; i++)
	{
		fread((char*)buffer, sizeof(int), 1, in);

		if(Trans->length >= Trans->maxlength)
			Trans->DoubleTrans(Trans->length);

		Trans->t[Trans->length] = *buffer;
		Trans->length++;
	}
#endif
	//transaction r transformed n recorded in the second scan
	if(bltranStore)
	{
		tranStore* newTran = new tranStore(Trans->length);
		memcpy(newTran->t, Trans->t, Trans->length*sizeof(int));
		
		/*j=0;
		for(i=0; i<Trans->length; i++)
		{
			//if(item_order[Trans->t[i]]!=-1) //exclude full items //wrong
			newTran->t[j++] = Trans->t[i];
		}*/

		//newTran->length = j;
		newTran->length = Trans->length;
		newTran->next = ts;
		ts = newTran;
	}
	
	return Trans;
}


int Data::readStat()
{
	if(!in)
		return 0;
	
	int i,j;
	Transaction *Tran = new Transaction;
	//assert(Tran!=NULL);

	//capture dataset informations
	for(i=0; i<4; i++)
	{
		getNextTransaction(Tran);
		switch(i)
		{
			case 0:
				TRANSACTION_NO = Tran->t[0];
				OLD_TRAN_NO = Tran->t[0];

				NET_ITEM_NO = Tran->t[1];
				OLD_ITEM_NO = Tran->t[2];
				fullNum = Tran->t[3]; //necessary! note
				VALID_ITEM_NO = NET_ITEM_NO-fullNum;
				OLD_VALID_ITEM_NO = VALID_ITEM_NO;
				break;
			case 1:
				item_support = (int*) buf->newbuf(NET_ITEM_NO+ITEMBUFF, sizeof(int));
				//item_support_new = (int*) buf->newbuf(NET_ITEM_NO+ITEMBUFF, sizeof(int));
				memcpy(item_support, Tran->t, INTSIZE*Tran->length);
				//memcpy(item_support_new, Tran->t, INTSIZE*Tran->length);
				for(j=Tran->length;j<NET_ITEM_NO+ITEMBUFF;j++)
				{
					item_support[j] = 0;
					//item_support_new[j] = 0;
				}
				break;
			case 2:
				//capture old order_item
				order_item = (int*) buf->newbuf(NET_ITEM_NO+ITEMBUFF, sizeof(int));
				
				memcpy(order_item, Tran->t, sizeof(int)*(VALID_ITEM_NO));
				//memcpy(order_item, Tran->t, sizeof(int)*(NET_ITEM_NO)); //include full items as well
				
				//for(j=NET_ITEM_NO; j<NET_ITEM_NO+ITEMBUFF;j++)
				for(j=VALID_ITEM_NO; j<NET_ITEM_NO+ITEMBUFF;j++)
					order_item[j] = -1; //remove item buff

				//init item_order
				item_order  = (int*) buf->newbuf(NET_ITEM_NO+ITEMBUFF, sizeof(int));
				for(j=0; j<NET_ITEM_NO+ITEMBUFF; j++)
					item_order[j] = -1;

				for(j=0;j<VALID_ITEM_NO; j++)
				//for(j=0;j<NET_ITEM_NO; j++)
					item_order[order_item[j]] = j;
				break;
			case 3:
				if(fullNum)
				{
					fullItem = (int*)buf->newbuf(fullNum, INTSIZE);
					memcpy(fullItem, Tran->t, INTSIZE*fullNum);
				}
				else
				{
					fullNum = 0;
					fullItem = NULL;
				}
				break;

		}
	}

	return 1;
}

int Data::getGCtree(FK_tree*& globalTree)
{
	
	globalTree->initArray(NET_ITEM_NO);
	getTree(globalTree);

	fclose(in);
	in = NULL;

	return 1;
}

EquiClass *Data::getNextEC(EquiClass* ec, int &support, int& index, K_tree *& ktree)
{
	 ec->clen = 0;
	
	char c;
	int item, pos;
	
	//capture index
	do{
		c = getc(in);
	}while(c!='[' && c != '\n' && !feof(in));

	do{
		item=0;
		pos=0;
		c = getc(in);
		while((c >= '0') && (c <= '9')) {
			item *=10;
			item += int(c)-int('0');
			c = getc(in);
			pos++;
		}
		if(pos)
			index = item;

	}while(c !=']' && c !='\n' && !feof(in));

	//capture closed patterns
	do{
		item=0;
		pos=0;
		c = getc(in);
		while((c >= '0') && (c <= '9')) {
			item *=10;
			item += int(c)-int('0');
			c = getc(in);
			pos++;
		}
		if(pos)
		{	
			if(item_order[item]!=-1) //exclude full items
				ec->closeSet[ec->clen++] = item_order[item];
		}
	}while(c !='(' && c !='\n' && !feof(in));

	sort(ec->closeSet, ec->closeSet+ec->clen);
	
	//capture support value
	do{
		item=0;
		pos=0;
		c = getc(in);
		while((c >= '0') && (c <= '9')) {
			item *=10;
			item += int(c)-int('0');
			c = getc(in);
			pos++;
		}
		if(pos)
			support = item;
	}while(c !=')' && c !='\n' && !feof(in));
	
	//capture key patterns
	int* iset;

	do{
		ec->klen = 0;
		do{
			item=0;
			pos=0;
			c = getc(in);
			while((c >= '0') && (c <= '9')) {
				item *=10;
				item += int(c)-int('0');
				c = getc(in);
				pos++;
			}
			//for debug
			/*if(item_order[item] < 0)
			{
				printf("item_order error\n");
				scanf("exit");
				exit(1);
			}*/

			if(pos)
				ec->key[ec->klen++] = item_order[item];

		}while(c !=';' && c !='\n' && !feof(in));
		
		if(ec->klen)
		{
			if(ktree==NULL)
			{
				ktree = (K_tree*)buf->newbuf(1, sizeof(K_tree));
				ktree->init(0);
			}

			sort(ec->key, ec->key+ec->klen);
			ktree->insertKey(ec->key, ec->klen);
			iset = (int*)buf->newbuf(ec->klen, sizeof(int));
			memcpy(iset, ec->key, ec->klen*sizeof(int));
			ECstorage->insertKey(iset, ec->klen, support, index);
		}

	}while(c !='\n' && !feof(in));
	
	// if end of file is reached, rewind to beginning for next pass
	if(feof(in)){
		rewind(in);
		
		//debug for memory leak 21/10/2004
		delete ec; 
		
		return 0;
	}
	
	return ec;
}

int Data::readNGB()
{
	char c;
	int item, pos;

	int* iset = new int[NET_ITEM_NO];
	int len = 0;
	int support =0;

	
	do{
		len=0;
		support=0;
		
		//capture nbg
		do{
			item=0;
			pos=0;
			c = getc(in);
			while((c >= '0') && (c <= '9')) {
				item *=10;
				item += int(c)-int('0');
				c = getc(in);
				pos++;
			}
			
			if(pos)
			{
				Insert(iset, len, item);
			}
			
		}while(c!='(' && c!= '\n' && !feof(in));
		
		//capture support
		do{
			item=0;
			pos=0;
			c = getc(in);
			while((c >= '0') && (c <= '9')) {
				item *=10;
				item += int(c)-int('0');
				c = getc(in);
				pos++;
			}
			
			if(pos)
				support = item;
		}while(c!='\n' && !feof(in));

		if(len)
		{
			int* nbg = (int*)buf->newbuf(len, INTSIZE);
			memcpy(nbg, iset, len*INTSIZE);
			
			ECstorage->insertNBG(nbg, len, support);
			//ECstorage->insertKey(nbg, len, support);
		}
		
	}while(!feof(in));
	

	// if end of file is reached, rewind to beginning for next pass
	if(feof(in)){
		rewind(in);
	}

	return 1;
}


////////// private functions ////////////////////

int Data::getTree(FK_tree* fptree)
{
	if(fptree==NULL)
	{
		printf("Cannot get GCtree.\n");
		scanf("exit");
		exit(1);
	}
	
	char c;
	int item, pos, support, itemname, depth = 0;

	Knode* current = fptree->Root;
	Knode* sib = NULL;

	c = getc(in);

	while(c!='#')
	{
		c = getc(in);
	}
	c = getc(in);
	c = getc(in);
	do{	
		do{
			//get item n support
			itemname=-1;
			support =0;
			sib = NULL;
			
			do{
				
				item=0;
				pos=0;
				while((c >= '0') && (c <= '9')) {
					item *=10;
					item += int(c)-int('0');
					c = getc(in);
					pos++;
				}
				//insert node
				if(pos)
				{
					if(itemname<0)
					{
						itemname = item;
						if(current->leftchild)
						{
							for(sib=current->leftchild; sib->rightsibling!=NULL; sib = sib->rightsibling);
						}
					}
					else
					{
						support = item;
						current = current->append(fptree, sib, itemname, support);
						if(depth<0)
						{
							printf("fptree depth error.\n");
							scanf("exit");
							exit(1);
						}
						bran[depth++]++;
					}
				}
				c = getc(in);
			}while(support<=0 && c!='/' && !feof(in));
		}while(c != '/' && !feof(in));
		
		
		
		while(c == '/')
		{
			current = current->par;
			depth--;
			c = getc(in);
		}
		
	}while(!feof(in) && c!= '\n');
	
	
	return 1;
}
