// ///////////////////////////////////////////////////////
// Copyright (1994) Columbia University
// Department of Biochemistry and Molecular Biophysics
//
// Author: Weider Chang, Ph.D
// ///////////////////////////////////////////////////////

#include "stack.h"
#include "starasso.h"
#include "llistobj.h"

extern int general_debug;

@implementation WDCStarLoopStack

- setCurrentLoopScope: object
{
  // never used !
  _currentLoopScope=object;
  return self;
}

- setCurrentValueScope: object
{
  _currentValueScope=object;
  return self;
}

- getCurrentLoopScope
{
  // useless !
  return _currentLoopScope;
}

- getCurrentValueScope
{
  return _currentValueScope;
}

- popToCurrentValueObjectAndReturnPreviousInputItem;
{
  id tempItem=0;
  while (_currentValueScope!=[self topObject]) tempItem=[self popObject];
  if (general_debug) 
    printf("popToCurrent: reduce number of object in stack to: %d %s\n", 
	   [self count], [[[self topObject] class] name]);  
  return tempItem;
}

- pushLoopItem: loopItem
{
  [[[self pushObject : loopItem] 
    pushObject : [[loopItem getValue] getContent]] 
   setCurrentValueScope : [self topObject]];
  if (general_debug) 
    printf("pushLoopItem: raise number of object in stack to: %d\n", 
	   [self count]);
  return self;
}

- reduceLoopItem
{
  id tempItem;
  if (general_debug) 
    printf("reduceLoopItem:before reduce, number of object in stack is: %d\n",
	   [self count]);
  if ([self count]>2){
    while (![self isEmpty] && 
	   ![self isLoopItem : [self topObject]]) [self popObject];
    [self setCurrentValueScope : [[self exchangeTop] topObject]];
    [self exchangeTop];
  }
  if (general_debug) 
    printf("reduceLoopItem:reduce number of object in stack to: %d\n", 
	   [self count]);
  return self;
}

- getNextInputItem: previousItem
{
  id previousValue, currentItem;
 
  if ([previousItem getValue])

  /*
  if (([previousItem getValue]) && ![self isLoopItem: previousItem])
  */
    /* 
      Previous item has a value and the the value is not type of
      "WDCStarItemAssocValue" (loop item), then the current item is 
      the one next to the "previousItem". This means the "previousItem" 
      has just been assigned a value to.
      */
    
    currentItem=[previousItem nextLink];
  else 
    { 
      /* The 1st value after a name loop */
      
      currentItem=[self popObject];
      if (general_debug) 
	printf("getNextInputItem: reduce number of object in stack to: %d\n"
	       , [self count]);      
      /* or the 2nd value after a name loop and the 1st value was assigned
	 to the topObject of nameScopeStack. The 1st and 2nd object on top 
	 of the stack are the same. One of them need to be removed and the 
	 current item is realy the one next to the topObject*/

      if ([self isEmpty]){
	[self pushObject : currentItem];
	if (general_debug) 
	   printf("getNextInputItem: raise number of object in stack to: %d\n"
		  , [self count]);
      }
      else 
	{
	  if (currentItem==[self topObject])
	    currentItem=[currentItem nextLink];
	}
      
     };
  
  /* If the looped items have been exhausted, set the currentItem to the
     1st item in the current value loop.
     */

  if (!currentItem)
    {
      [self popToCurrentValueObjectAndReturnPreviousInputItem];
      currentItem=[self topObject]; 
    } 
  else 
    {

    /* if the current item is a _loop item then the 1st data item in the value 
       slote is the true current item. Push the currentItem and the "true" 
       current item into the stack. The value loop scope should be raised to 
       the true current item level as well.
       */
    
      if ([self isLoopItem: currentItem]) 
	currentItem=[[self pushLoopItem : currentItem] topObject];
    }
  return currentItem;
}

- (BOOL)isLoopItem: item
{
  return ([item isKindOfClassNamed: "WDCStarItemAssocValue"] &&
	  ![[item getNameString] compareCString:"loop_" ignoreCase:YES]);
}


@end

