#ifndef _pickobject_c_
#define _pickobject_c_

#include<stdlib.h>
#include<string.h>
#include<math.h>

struct AttrValPairStruct
{
  int mAttr;
  int *mAttrVal;
  int mSize;
};
typedef struct AttrValPairStruct AttrValPair;

struct PickObjectStruct
{
  AttrValPair *mPicked;
  float mScore;
  float mEffort, mPD, mPF;
  int mSize;
  float mSupport;
};
typedef struct PickObjectStruct PickObject;

PickObject *clone( PickObject *po )
{
  PickObject *newPO;
  int att, attVal;

  newPO = (PickObject*)malloc( sizeof( PickObject ) );
  newPO->mScore = po->mScore;
  newPO->mEffort = po->mEffort;
  newPO->mPD = po->mPD;
  newPO->mPF = po->mPF;
  newPO->mSupport = po->mSupport;
  newPO->mSize = po->mSize;
  newPO->mPicked = (AttrValPair*)malloc( sizeof( AttrValPair ) * po->mSize );
  for ( att = 0; att < po->mSize; att++ )
  {
    newPO->mPicked[att].mAttr = po->mPicked[att].mAttr;
    newPO->mPicked[att].mSize = po->mPicked[att].mSize;
    newPO->mPicked[att].mAttrVal = (int*)malloc( sizeof( int ) * po->mPicked[att].mSize );
    for ( attVal = 0; attVal < po->mPicked[att].mSize; attVal++ )
      newPO->mPicked[att].mAttrVal[attVal] = po->mPicked[att].mAttrVal[attVal];
  }
  
  return newPO;
}

int compareInts( const int *i, const int *j )
{
  int x = *i, y = *j;
  return *i - *j;
}

int findAttr( int val, AttrValPair *avp, int size )
{
  int i;
  for ( i = 0; i < size; i++ )
    if ( avp[i].mAttr == val ) return i;

  return -1;
}

int findAttrVal( int val, int *avs, int size )
{
  int i;
  for ( i = 0; i < size; i++ )
    if ( avs[i] == val ) return i;
  
  return -1;
}

void *setupPickObject( void *t )
{
  PickObject *toRet;
  float *vals = (float*)t;
 
  toRet = (PickObject*)malloc( sizeof( PickObject ) );
  toRet->mPicked = (AttrValPair*)malloc( sizeof( AttrValPair ) );
  toRet->mPicked[0].mAttr = (int)vals[0];
  toRet->mPicked[0].mAttrVal = (int*)malloc( sizeof( int ) );
  toRet->mPicked[0].mAttrVal[0] = (int)vals[1];
  toRet->mPicked[0].mSize = 1;
  toRet->mSize = 1;

  return toRet;
}

void deletePickObject( void *t )
{
  PickObject *po = (PickObject*)t;
  free( po->mPicked->mAttrVal );
  free( po->mPicked );
}

float comparePickObject( void *i, void *j )
{
  PickObject *po1 = (PickObject*)i, *po2 = (PickObject*)j;

  return  po1->mScore - po2->mScore;
}

float getScorePickObject( void *t )
{
  return ((PickObject*)t)->mScore;
}

float scorePickObject( void *i )
{
  return rand()/(float)RAND_MAX * 100.0;
}

void *combinePickObject( void* i, void *j  )
{ 
  if ( i == NULL && j == NULL ) return NULL;
  if ( i == NULL && j != NULL ) return j;
  if ( i != NULL && j == NULL ) return i;				  

  PickObject *toRet = (PickObject*)malloc( sizeof( PickObject ) ),
    *po1 = (PickObject*)i,
    *po2 = (PickObject*)j;
  int x, y, count = 0;

  toRet->mPicked = (AttrValPair*)malloc( po1->mSize * sizeof( AttrValPair ) );
  toRet->mSize = po1->mSize;
  
  for ( x = 0; x < po1->mSize; x++ )
  {
    toRet->mPicked[x].mAttr = po1->mPicked[x].mAttr;
    toRet->mPicked[x].mAttrVal = (int*)malloc( po1->mPicked[x].mSize * sizeof( int ) );
    for ( y = 0; y < po1->mPicked[x].mSize; y++ )
      toRet->mPicked[x].mAttrVal[y] = po1->mPicked[x].mAttrVal[y];
    toRet->mPicked[x].mSize = po1->mPicked[x].mSize;
  }
    
  for ( x = 0; x < po2->mSize; x++ )
  {
    int attrPos = findAttr( po2->mPicked[x].mAttr, toRet->mPicked, toRet->mSize );
    // If we are an attribute not in this pair, make a new attribute value pair
    if ( attrPos == -1 )
    {
      toRet->mPicked = (AttrValPair*)realloc( toRet->mPicked, ( toRet->mSize + 1 ) * sizeof( AttrValPair ) );
      toRet->mPicked[toRet->mSize].mAttr = po2->mPicked[x].mAttr;
      toRet->mPicked[toRet->mSize].mAttrVal = (int*)malloc( po2->mPicked[x].mSize * sizeof( int ) );
      for ( y = 0; y < po2->mPicked[x].mSize; y++ )
	toRet->mPicked[toRet->mSize].mAttrVal[y] = po2->mPicked[x].mAttrVal[y];
      toRet->mPicked[toRet->mSize].mSize = po2->mPicked[x].mSize;
      toRet->mSize++;
      count++;
    }
    // Else this attribute already exists, so only add our disjunctions that aren't found.
    else
    {
      for ( y = 0; y < po2->mPicked[x].mSize; y++ )
      {
	int attrValPos = findAttrVal( po2->mPicked[x].mAttrVal[y], toRet->mPicked[attrPos].mAttrVal, toRet->mPicked[attrPos].mSize );
	// If we are a disjunction not yet found, add us.
	if ( attrValPos == -1 )
	{
	  toRet->mPicked[attrPos].mAttrVal = (int*)realloc( toRet->mPicked[attrPos].mAttrVal, ( toRet->mPicked[attrPos].mSize + 1 ) * sizeof( int ) );
	  toRet->mPicked[attrPos].mAttrVal[toRet->mPicked[attrPos].mSize] = po2->mPicked[x].mAttrVal[y];
	  toRet->mPicked[attrPos].mSize++;
	  count++;
	}
      }
    }
  }
  
  if ( count <= 0 )
  {
    deletePickObject( toRet );
    free( toRet );
    toRet = NULL;
  }

  return toRet;
}

#endif
