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

#include <string.h>
#include <stdlib.h>
#include "diction.h"
#include "datablk.h"
#include "iterator.h"
#include "llistobj.h"
#include "idxcoltn.h"

extern int general_debug;

@implementation WDCDictionary

#include "starutig.m"

- init;
{
  [super initEncoding:@encode(WDCStarDataBlock*) 
         keyEncoding:@encode(WDCString*)];
  return self;
}

- free
{
  [_appSpecObject free];
  [_globalBlock free];
}

- setName:(const char*)aName
{
  return [self setNameString:[[WDCString alloc]
                            initFromCString:(char*)aName]];
}

- setAppSpecObject:anObject
{
  _appSpecObject=anObject;
  return self;
}

- setGlobalBlock:block
{
  _globalBlock=block;
  return self;
}

- setDictionary:(WDCDictionary*)dictionary
{
  _dictionary=dictionary;
  return self;
}

- (WDCDictionary*)getDictionary
{
  return _dictionary;
}

- getGlobalBlock
{
  return _globalBlock;
}

- getAppSpecObject
{
  return _appSpecObject;
}

- (const char*)getName
{
  return [_name cStringValue];
}

- getNameString
{
  return _name;
}

- getDefinitionBlockAtKey:(const char*)aName
{
  id temp_id, string=[[[WDCString alloc] 
		       initFromCString :(char*)aName] setToLowerCase];
  elt temp;
  BOOL notFound=NO;
  elt err(arglist_t argFrame)
    {
      if (general_debug)
	printf("Dictionary element at key %s not found.\n",aName);
      notFound=YES;
      return 0;
    };
  temp=[self elementAtKey:(WDCString*)string ifAbsentCall:err];
  if (!notFound)
      temp_id=temp.id_u;
  else
      temp_id=0;
  [string free];
  return temp_id;
}

- setNameString: nameString;
{
  if (_name) [_name free];
  _name=nameString;
  return self;
}

- getAllDataItems:(const char*)anItemName ofCategory:(const char*)aCategoryName
{
  id itemlist=0;
  id list=[self getDefinitionBlocksWhos:"_category" 
	   is : (char*)aCategoryName];
  id iter;
  if (list){
    iter=[[WDCListIterator alloc] initFrom:list];
    while ([iter goNext]){
      if (itemlist)
	[itemlist joint:[[[iter getCurrentObject]
			getValue] getAllItemsNamed :anItemName]];
      else
	itemlist=[[[iter getCurrentObject]
		   getValue] getAllItemsNamed :anItemName];
    }
    [list free];
    [iter free];
  }
  return itemlist;
}

- getAllCategoriesAre:(const char*)aRelation 
 ofCategory:(const char*)aCategory
{
  id categories=0, iter;
  id list=[self getAllDataItems:aRelation ofCategory:aCategory];
  char* itemname, *datablockname;
  if (list){
    iter=[[WDCListIterator alloc] initFrom:list];
    while ([iter goNext]){
      itemname=(char*)[[[[iter getCurrentObject] 
			 getContent] getValue] cStringValue];
      datablockname=(char*)malloc(sizeof(char)*(strlen(itemname)+5));
      
      // ************************************************
      // I might want to do something about this code
      // it has been used in many place.
      // *************************************************

      strcpy(datablockname, "data");
      if (itemname[0]!='\'')
	strcat(datablockname, itemname);
      else
	strncat(datablockname, &itemname[1], strlen(itemname)-2);
      // ***********************************************
      if (categories)
	[categories merge:[[self getDefinitionBlockAtKey:datablockname]
			   getAllDataItems :"_category"]];
      else
	categories=[[self getDefinitionBlockAtKey:datablockname]
		    getAllDataItems :"_category"];
    }
    [list free];
    [iter free];
  }
  return categories;
}

- addDataItem: item
{
  id string, list, iter;
  char name[50], *currentkey;
  if (list=[item getAllDataItems :"_name"]){
    iter=[[WDCListIterator alloc] initFrom:list];
    while ([iter goNext]){
      currentkey=(char*)[[[[iter getCurrentObject] 
			   getContent] getValue] cStringValue];
      strcpy(name, "data");
      if (currentkey[0]!='\'')
	strcat(name, currentkey);
      else
	strncat(name, &currentkey[1], strlen(currentkey)-2); 
      string=[[[WDCString alloc] initFromCString: name] setToLowerCase];
      [self insertElement:item atKey:(WDCString*)string];
    }
  }
  else {
    strcpy(name, [item getName]);
    string=[[[WDCString alloc] initFromCString: name] setToLowerCase];
    [self insertElement:item atKey:(WDCString*)string];
  }
  return [self addSaveFrameIndexesOf: item];
}

- addSaveFrameIndexesOf: item
{
  id iter1, list2, iter2, current, string;
  char name[50], *currentkey;
  iter1=[[WDCListIterator alloc] initFrom: [item getValue]];
  while ([iter1 goNext]) {
    current=[iter1 getCurrentObject];
    if ([current isMemberOfClassNamed:"WDCStarDataBlock"] &&
	[current isSaveFrame]) {
      if (list2=[current getAllDataItems :"_name"]){
	iter2=[[WDCListIterator alloc] initFrom:list2];
	while ([iter2 goNext]){
	  currentkey=(char*)[[[[iter2 getCurrentObject] 
			       getContent] getValue] cStringValue];
	  strcpy(name, "data");
	  if (currentkey[0]!='\'')
	    strcat(name, currentkey);
	  else
	    strncat(name, &currentkey[1], strlen(currentkey)-2); 
	  string=[[[WDCString alloc] initFromCString: name] setToLowerCase];
	  [self insertElement:current atKey:(WDCString*)string];
	}
      }
      else {
	strcpy(name, "data");
	strcat(name, strchr([current getName], '_'));
	string=[[[WDCString alloc] 
		 initFromCString : name] setToLowerCase];
	[self insertElement:current atKey:(WDCString*)string];
      }
    }
  }   
  return self;
}

- printForDebugger
{
  int i=0;
  id iter, current_id;
  printf("(%s\n", [self name]);
  printf(" _name:%s\n Contents the following elements:\n",[self getName]);
  printf(" Just the _name Item\n");
  iter=[[WDCListIterator alloc] initFrom:self];
  while ([iter goNext]){
    printf("\n<Dictionary element %d>:\n", ++i);
    printf(" _name is :%s\n",[[iter getCurrentObject] getName]);
    [[[iter getCurrentObject] getDataItem:"_category"] printForDebugger];
  }
  printf(")\n");
  [iter free];
  return self;
} 



@end





