/***************************************************************

Description:
  This is a a taylored linked list system for holding noncontent editor data. 
   Nodes are sorted by owner, then index. they are sorted at creation time.

 This code could be optimized by keeping the tag list sorted by owner and
   index, but in the hurry to get it to work, wasn't done.

Methods:
  -- shared methods --
  int    set   (owner, index, position, type);  // should be ces_error_t
  int    set   (tag *);                         // should be ces_error_t
  tag  * get   (owner, index, tag *);
  tag  * find  (owner, index);
  bool   removeNode(owner, index);              // should be ces_error_t, should be called delete
  
  to_be_created_methods:
  
  int    ComparePos(tag * A, tag * B);          
    -1 = B is before A
     0 = same position
     1 = B is after A
  
  ces_error_t   UpdatePos (start_position, +-characters); //linked with main accum

  -- internal methods --


 Dont use tab characters in this code.
  Dont use tab characters in this code.
   Dont use tab characters in this code.
    Dont use tab characters in this code.
     Dont use tab characters in this code.
      Dont use tab characters in this code.
       Dont use tab characters in this code.
        Dont use tab characters in this code.
         Dont use tab characters in this code.
          thanks.

History: 
 <Jul 8  2002> Creation Dan, 
 <Jul 26 2002> modified to use new linked list code. Jeff, 
 <JUl 28 2002> modified for working out iterator bugs, and set, dan
 <Nov 21 2003> comments added, dan 
 <Dec 11 2003> added new search routine 'locate', dan
 <dec 16 2003> changed set returns to CESError_t, dan
 
see proptypes.h for prop types
 

***************************************************************/

#include <stdlib.h>
//#include <string.h>
#include "cestypes.h" 
#include "propaccumulator.h" // class definition
//#include "dll.h"       // dual linked lists...

#include "stdio.h"  //printf



PropAccum::PropAccum() {
  // initialize the linked list.
  //propList = NULL;
}

PropAccum::~PropAccum() {
   //deleteAll();
}

/*************************************************
*
* FREE THE NODES. FREE ALL THE NODES. FREE THEM NOW!
*
**************************************************/
void PropAccum::deleteAll() {

   propList.erase(propList.begin(),propList.end());
}


/*****************************************
*
* Description:
*  try to find (owner, index) node 
*  if  not found - create
*    if found -modify other attributes
*  else err
*
* In:
*  Owner:    level 1 identity. e.g. the 
*    client identity.
*  Index:    level 2 identity. e.g. the 
*    bookmark number of the client.
*  Position: The character offset of this
*    tag. the purpose for its existance.
*  Type:     Used when interperting tags
*             to know what it is e.g.
*             cursor or bookmark.
*
* Out:
*  1 = success
*  0 = failure
*
* converted.
*****************************************/
CESError_t PropAccum::set(BIGNUM Owner, BIGNUM Index, BIGNUM Position, int Type) {

  Tag * node; // cesfieldtag is same as tagnode

  //printf("propaccum:set -> checking for owner %ld, index %ld\n", Owner, Index);

  // lookup tag
  node = find(Owner, Index);
  // if the tag dosn't exist
  if (node == NULL) {         
    if (insert(Owner, Index, Position, Type)) {  // create tag  // if the tag exists            
      return NoError;
    } else {
      return OutputError; // fail! fail!
    }   
  } else {
    modify(node, Position, Type);
  }
   
  return NoError; // in some form, shape , or manner, it worked.
}

/****************************************
*
* Find a node with the given owner and index.
*
* IN:
*   Owner: find a tag with a matching owner and
*   Index: find a tag with a matching index
*
* OUT:
*   Success: Pointer to tag
*   Failure: NULL   
*
*  !!!???!!! we need a search method that can allow us to look for 
*     other properties that might occur more than once, hence the 
*     need for continuable searches
*
* converted.
****************************************/
Tag * PropAccum::find(BIGNUM owner, BIGNUM index) {

  //const_iterator<Tag> iterator( propList.cBegin());
  iter<Tag> iterator( propList.begin());
  //for ( ;iterator != propList.cEnd(); iterator++)

  //printf("propaccum:find -> seeking owner %ld, index %ld\n", owner, index);

  for ( ;iterator != propList.end(); iterator++)
  {
  /*
    BIGNUM temp;

    temp = iterator.getPointAt()->getValue().getOwner();
    printf("propaccum:find -> found owner %ld\n", temp);

    if ( temp == owner) {

      printf("propaccum:find -> owner matches\n");
      temp = iterator.getPointAt()->getValue().getIndex();
      printf("propaccum:find -> found index %ld\n", temp);

       if ( temp == index) { //found

	 printf("propaccum:find -> index matches\n");
//        return &(iterator.getPointAt()->getValue());
          return (iterator.getPointAt()->getValPtr());
          //means iterator.nodepointer()->getValue()

       }
    }
*/
    
     if (iterator.getPointAt()->getValue().getOwner() == owner)
       if (iterator.getPointAt()->getValue().getIndex() == index) { //found
          return (iterator.getPointAt()->getValPtr());
       }
    
  }
  return NULL;//not found
  
}


/****************************************
*
* Find a node with any combo of owner, index, type, or position,
*   where items not to be searched for are 0
*
* IN:
*   Owner:    find a tag with a matching owner     and / or
*   Index:    find a tag with a matching index     and / or
*   Type:     find a tag with a matching type      and / or
*   Position: find a tag with a matching position  and / or
*
* OUT:
*   Success: Pointer to tag
*   Failure: NULL   
*
*  !!!???!!! we need a search method that can allow us to look for 
*     other properties that might occur more than once, hence the 
*     need for continuable searches, which means we need a structure
*     or object to hold our position data between searches
*
****************************************/
Tag * PropAccum::locate(BIGNUM owner, BIGNUM index, TagType type, ChrOffset position) {

  iter<Tag> iterator( propList.begin());

  for ( ;iterator != propList.end(); iterator++) {    
   if ((iterator.getPointAt()->getValue().getType() == type) || (type == 0) )
     if ((iterator.getPointAt()->getValue().getPosition() == position) || (position == 0) )
       if ((iterator.getPointAt()->getValue().getOwner() == owner) || (owner == 0) )
         if ((iterator.getPointAt()->getValue().getIndex() == index) || (index == 0) ) { //found
           return (iterator.getPointAt()->getValPtr());
         }
             
  }
   
  return NULL; //not found
  
}




/*****************************************************
 *
 * Insert a data set into the linked list.
 *
 * IN:
 *  Owner:    Main identity number
 *  Index:    Sub identity number
 *  Position: Value to set position to
 *  Type:     Tag type to set 
 *
 * OUT:
 *  1 = success
 *  0 = failure
 *
 * converted.
 ****************************************************/
int PropAccum::insert(BIGNUM owner, BIGNUM index, BIGNUM position, int type) {

  //printf("propaccum:insert called %ld %ld %ld %ld\n", owner, index, position, type);

  Tag temp(owner, index, position, type);
  /*
  Tag temp;
  
  temp.setOwner(owner);  // the hard way? what do you mean? <-slow way...  jm
  temp.setIndex(index);
  temp.setPosition(position);
  temp.setType(type);
  */
  propList.push_back(temp);
  
  iter<Tag> temp2(propList.begin());
  /*
  printf("propaccum:insert confirm: %ld %ld %ld %ld\n",
     temp2.getPointAt()->getValue().getOwner(),
     temp2.getPointAt()->getValue().getIndex(),
     temp2.getPointAt()->getValue().getPosition(),
     temp2.getPointAt()->getValue().getType()
  );
  */
  return 1;
  
  //to check validity would get the back of the proplist and see what contents were.
  
}


//    modify(node, Position, Type);
/************************************************
 *
 * Modify the data of a node.
 * Why is this a method instead of just doing it?
 *  ... I dont know...
 *
 * IN:
 *  node:      Pointer to the node to modify
 *  Position:  The new value for the Position
 *  Type:      The new value fot the Type
 *
 * OUT:
 *  void
 *
 * converted.
 ***********************************************/
void PropAccum::modify(Tag * node, BIGNUM Position, BIGNUM Type) {
  
  //printf("propaccum:modify called %ld %ld\n", Position, Type);
  
  node->setPosition(Position);
  node->setType(Type);

  // whoo! that was a tuffie!, hope I didn't make any ERRorS!

  return;
}


/*
* Direct Method
*/
CESError_t PropAccum::set(Tag * Data) {
  
  // !!!???!!! Write me!
  printf("PropAccum::Set(CES_FIELD_TAG *) was called, but hasn't been written yet.\n");
  
  return NoCode;
}

/*****************************************
*
* Description:
*  Get a tag.
*
* In:
*  Owner:    level 1 identity. e.g. the 
*    client identity.
*  Index:    level 2 identity. e.g. the 
*    bookmark number of the client.
*  Dest:     pointer to a tag to put the
*    result in.
*
* Out:
*  Success: Same as Dest.
*  Failure: NULL
*
* !!!???!!! it Would be nice to be able to pull just one property of a tag
*
* converted.
*****************************************/
Tag * PropAccum::get(BIGNUM Owner, BIGNUM Index, Tag * Dest) {

  Tag * node;
  
  // find it.
  node = find(Owner, Index);
  
  // if the tag exists
  if (node != NULL) {
    // set tag
    Dest->setPosition( node->getPosition());
    Dest->setOwner(    node->getOwner()   );
    Dest->setIndex(    node->getIndex()   );
    Dest->setType(     node->getType()    );
    return Dest;
  } 
  
  return NULL;
}








