/*  Hipparcos ASCII CD-ROM load and search routines Release 1.1 June 1997
    William O'Mullane 
    Astrophysics Division, ESTEC, Noordwijk, The Netherlands. 
    See the readme.pdf file for more information */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "utils.h" 
#include "dmsa_o.h" 


FILE* jump_dmsa_o (long recNum) 
{
   static int init=0;
   static FILE* dataFile;
   if (init==0)
   {
      if ((dataFile = fopen ("../notes/dmsa_o.doc","r")) == NULL)
      {
         fprintf(stderr,"Could not open ../notes/dmsa_o.doc \n");
         return NULL;
      }
      init=1;
   }
   if ( fseek (dataFile, (recNum - 1) * dmsa_o_REC_LEN, 0) == 0)
     return dataFile;
   else
     return NULL;
}


int print_dmsa_o (dmsa_o* entry, int decode) 
{
/*  Just print out each attribute with its value  */
   char outputStr[50];
   if (entry == NULL) 
   {
      fprintf (stderr,"print_dmsa_o NULL pointer for entry\n");
      return (-1);
   }

	INTasStr((char *)&outputStr,"%8d",&entry->DO16 );
	printf("DO16  : %s             Reference number\n",outputStr);
	INTasStr((char *)&outputStr,"%8d",&entry->DOM3 );
	printf("DOM3  : %s             Number of records N for this reference\n",outputStr);
	INTasStr((char *)&outputStr,"%8d",&entry->DOM4 );
	printf("DOM4  : %s             Sequential number (1 to N) for this record\n",outputStr);
	printf("DOM5  : %72.72sText of reference\n",entry->DOM5 );
   return (0);
} /* End of print_dmsa_o */

int print_dmsa_o_cols (dmsa_o* entry, int decode) 
{
   char outputStr[200];
/*  print attributes accross screen as in datafile - 
    decode fields depending on the value of decode (values defined in utils.h */
   if (entry == NULL) 
   {
      fprintf (stderr,"print_dmsa_o_cols NULL pointer for entry\n");
      return (-1);
   }

	INTasStr((char *)&outputStr,"%3d",&entry->DO16);
	printf("%s",outputStr);
	INTasStr((char *)&outputStr,"%1d",&entry->DOM3);
	printf("|%s",outputStr);
	INTasStr((char *)&outputStr,"%1d",&entry->DOM4);
	printf("|%s",outputStr);
	printf("|%72s",entry->DOM5);
	printf("\r\n");
	return (0);
} /* End of print_dmsa_o_cols */

int print_dmsa_o_header () 
{
/*  print col names accross screen as in datafile */

	printf("O16|3|4|DOM5                                                                    \n");
   return (0);
} /* End of print_dmsa_o_headre */



int load_dmsa_o (char* ifile,dmsa_o* index) 
{
/* Routine to load an index from a file. The structure for the index must
 * already exist as must the file of course
 */
   dmsa_o idx;
   FILE *fp;
   int i;

   if ( (fp=fopen(ifile,"r"))==NULL)
   {
	fprintf(stderr,"load_dmsa_o unable to open %s \n",ifile);
	return (-1);
   }
   if (index == NULL) 
   {
      fprintf (stderr,"load_dmsa_o NULL pointer for index\n");
      return (-1);
   }
   /*printf("Loading index dmsa_o from %s.. ",ifile);*/
   for (i=0;i<dmsa_o_entries;i++)
   {
	if ( (getnext_dmsa_o (fp,&index[i])) != 0)
   	{
	   fprintf(stderr,"load_dmsa_o problem with entry %d \n",i);
	   break;
	}
   /*     if  ( (i % 5000) == 0) printf("#");*/
   }
   if ( i < dmsa_o_entries) 
   {
	fprintf(stderr,"Premature end of index file \n");
   	return -1;
   }
   /* printf(" done \n"); */
   return 0;
} /* End of load_dmsa_o*/

int getnext_dmsa_o (FILE* fp, dmsa_o* entry)
{
   char buffer[dmsa_o_REC_LEN + 2];
   if (fgets((char *)&buffer,dmsa_o_REC_LEN+1,fp))
   { 
	char delimiter[3]="|\r\0";
	char *token=strtok((char *)&buffer,(char *)&delimiter); 
	strAsINT(token,&entry->DO16);
	token=strtok(NULL,delimiter);
	strAsINT(token,&entry->DOM3);
	token=strtok(NULL,delimiter);
	strAsINT(token,&entry->DOM4);
	token=strtok(NULL,delimiter);
	strcpy((char *)&entry->DOM5,token);
   return 0;
   }
   else
        return -1;
} /* End of getnext_dmsa_o */

dmsa_o* find_dmsa_o (INT* key)
{
   static int init=0;
   static dmsa_o index[dmsa_o_entries];
   int mid,lpos,rpos,found;
   if (init == 0)
   {
        if (load_dmsa_o("../notes/dmsa_o.doc",(dmsa_o*)&index) !=0)
             return NULL;
        init=1;
   }

   /*  Binary search */ 
   rpos = dmsa_o_entries; 
   lpos = key->value - 1;
   if (rpos > dmsa_o_entries) rpos = dmsa_o_entries;
   found = 0;
   while (!found && !(lpos==mid && rpos==mid || lpos > rpos))
   {
	mid =  (rpos + lpos) /2;
        found = index[mid].DO16.value == key->value;
     	if (key->value > index[mid].DO16.value )
	   lpos = mid+1;
	else
	   if (key->value < index[mid].DO16.value)
	      rpos = mid;
	/*printf (" %d,%d Betweeen %d,%d and %d,%d Key = %d\n",mid,index[mid].D016.value,lpos,index[lpos].D016.value,rpos,index[rpos].D016.value,key->value);*/
   }
   if (found)
   {
	/*Go back to first entry for this ref*/
	while (key->value == index[mid].DO16.value)
	   mid--;
	return &index[mid+1]; /* because we are now at the one before */
   } 
   else
   {
      return NULL;
   }
   
} /* End of find_dmsa_o */


/*  array routines  */ 
int print_array_dmsa_o_cols (array_dmsa_o* array, int decode) 
{
   int i;
   if (array == NULL) 
   {
      fprintf (stderr,"print_array_dmsa_o NULL pointer for entry\n");
      return (-1);
   }
/*   printf("Array array_dmsa_o contains %d entries :\n",array->no_entries);*/
      if (array->no_entries > 0)
      {
         print_dmsa_o_header();
      }
      for (i=0; i<array->no_entries; i++)
      {
	 print_dmsa_o_cols (&array->data[i],decode) ;
      }
      return (0);
} /* End of print_array_dmsa_o_cols */

int print_array_dmsa_o (array_dmsa_o* array, int decode) 
{
   int i;
   if (array == NULL) 
   {
      fprintf (stderr,"print_array_dmsa_o NULL pointer for entry\n");
      return (-1);
   }
/*   printf("Array array_dmsa_o contains %d entries :\n",array->no_entries);*/
      for (i=0; i<array->no_entries; i++)
      {
	 print_dmsa_o (&array->data[i],decode) ;
      }
      return (0);
} /* End of print_array_dmsa_o */


dmsa_o* search_dmsa_o (INT* key, array_dmsa_o* array)
{
   dmsa_o* recNum = NULL;
   FILE* dataFile=NULL;
   if (key->isValid)
       	recNum=find_dmsa_o(key);
   if (recNum != NULL)
   {
     /* got the first entry in the array for this ref */
     array->data = recNum; 
     array->no_entries = recNum->DOM3.value;
     return recNum;
   }
   else
   {
      array->no_entries = 0;
      return NULL;
   }
}
