/**************************************************************************
* File:	       fits_obj.c
* Programmers: Anne Raugh
*              Dorian Winterfeld
* Institution: PDS/Small Bodies Node
*              University of Maryland
* Date:	       March 21, 1995
* Abstract:    Function implementations for FITS object routines.
* Description:
***************************************************************************/

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "fits_obj.h"
#include "pds_tbl.h"
#include "pdserror.h"
#include "pds_util.h"

/*****************************************************************************
* Function: 	setup_FITS_object
* Abstract:    initializes FITS object
* Description:
* Input
*			ttable - pointer to translation table
* Output
*			main_object - pointer to primary FITS header object
* Return
*        TRUE for success; FALSE otherwise
******************************************************************************/
int setup_FITS_object(table *ttable,FITS_object **main_object )
{
	char obj_type[50];       /* type of object, from translation table */
	FITS_object *ext_object; /* pointer to extension header object */

/* get object type from the translation table */
	get_subobj(ttable->PDS_form,obj_type);

/* create main  object */
	*main_object = create_FITS_object(obj_type,NULL);

/* if it's NULL, then return error */
	if (*main_object == NULL) return MALLOC_ERROR;

/* if object is a table, create the TABLE extension object */
	if (!strcmp(ttable->PDS_form,"ASCII_TABLE")) 
		  ext_object = create_FITS_object("TABLE",*main_object);           
/* if object is a binary table, create BINTABLE extension object */
	if (!strcmp(ttable->PDS_form,"BINARY_TABLE"))
	    ext_object = create_FITS_object("BINTABLE",*main_object);

	if (ext_object == NULL) return MALLOC_ERROR;

	return OK;
} /* end setup_FITS_object */


/*****************************************************************************
* Function: get_subobj
* Abstract: extracts the PDS object char string out of the PDS form string.
* Inputs
*	PDS_form: char string holds PDS form from User Translation table.
* Outputs
*	subobject: holds PDS object Character string.
*****************************************************************************/
void get_subobj(char *PDS_form,char *subobj)
{
  char *subobj_ptr;  /* last part of PDS form */
  char form[50];     /* local copy of PDS_form */
  char *tmp_ptr;     /* token pointer */

  strcpy(form,PDS_form);

  tmp_ptr = strtok(form,"_");

  while (tmp_ptr != NULL){
	subobj_ptr = tmp_ptr;
	tmp_ptr = strtok(NULL,"_");
  }
  
  strcpy(subobj,subobj_ptr);
 
} /* end get_subobj */


/*****************************************************************************
* Function: create_FITS_object
* Abstract: Routine to create a new FITS object of the named type, and add it
*	  to the end of the object list attached to the main object.
* Description:
* Input
*			  type: type of FITS header
*			  pointer to primary header object
* Return:
*          pointer to new FITS object
******************************************************************************/
FITS_object *create_FITS_object(char *type, FITS_object *main)
{
	FITS_object *new_object;
	FITS_object *object_ptr;
	FITS_keyword *key;

/* allocate space for new object and initialize fields */
	if((new_object = (FITS_object *)malloc(sizeof(FITS_object))) == NULL)
		return NULL;

/* Check if this is the PRIMARY HEADER OBJECT */
	 if (main == NULL) {
		  new_object->extension = FALSE;
		  strcpy(new_object->name,type);
		  new_object->ext_cnt = 0;
		  new_object->prev = new_object->next = NULL;
   }
	else {
/* EXTENSION OBJECT */
		  new_object->extension = TRUE;
		  if (main->ext_cnt == 0) {
			key = create_FITS_keyword("EXTEND", main);
			strcpy(key->type,"LOGICAL");
			key->value = (char *)malloc(2);
			strcpy(key->value,"T");
		  }
		  main->ext_cnt++;
		  strcpy(new_object->name,type);
	}
  
/* add the required keywords for the given object type */
	add_required_keys(new_object);
 
/* Link the new object onto the end of the object list  */
	if (main != NULL) {
		object_ptr = main;
		while (object_ptr->next != NULL)
			object_ptr = object_ptr->next;

		object_ptr->next = new_object;
		new_object->prev = object_ptr;
		new_object->next = NULL;
	}
    
	return new_object;
} /* end create_FITS_object */

/*****************************************************************************
* Function: add_required_keys
* Abstract: Routine to add the required FITS keywords of the given FITS object
* Input
*				object: pointer to FITS object
* Return:
*				TRUE on success
******************************************************************************/
int add_required_keys(FITS_object *object) {
	FITS_keyword *key; /* pointer to new FITS key */

/* PRIMARY HEADER */
	if (object->extension == FALSE) {
		key = create_FITS_keyword("SIMPLE",object);
		strcpy(key->type,"LOGICAL");
		key->value = (char *)malloc(2);
		strcpy(key->value,"T");
		key->required = TRUE;
		if (strcmp(object->name,"IMAGE") == 0){
			key = create_FITS_keyword("BITPIX",object);
			strcpy(key->type,"INTEGER");
			key->required = TRUE;
			key = create_FITS_keyword("NAXIS",object);
			strcpy(key->type,"INTEGER");
			key->required = TRUE;
                        key->value = (char *)malloc(2);
                        strcpy(key->value,"2");
			key = create_FITS_keyword("NAXIS1",object);
			strcpy(key->type,"INTEGER");
			key->required = TRUE;
			key = create_FITS_keyword("NAXIS2",object);
			strcpy(key->type,"INTEGER");
			key->required = TRUE;
			key = create_FITS_keyword("NAXIS3",object);
		}
		if ((strcmp(object->name,"TABLE") == 0) ||
			(strcmp(object->name,"BINTABLE") == 0)) {
			key = create_FITS_keyword("BITPIX",object);
			strcpy(key->type,"INTEGER");
			key->value = (char *)malloc(2);
			strcpy(key->value,"8");
			key = create_FITS_keyword("NAXIS",object);
			strcpy(key->type,"INTEGER");
			key->value = (char *)malloc(2);
			strcpy(key->value,"0");
		}
	}
	else
/* EXTENSION HEADER OBJECT */
	if (object->extension == TRUE) {
		if (strncmp(object->name,"IMAGE",5) == 0) {
			key = create_FITS_keyword("XTENSION",object);
			strcpy(key->type,"CHARACTER");
			key->value = (char *)malloc(12);
			strcpy(key->value,"'IMAGE   '");
			key->required = TRUE;
			key = create_FITS_keyword("BITPIX",object);
			strcpy(key->type,"INTEGER");
			key->required = TRUE;
			key = create_FITS_keyword("NAXIS",object);
			strcpy(key->type,"INTEGER");
			key->value = (char *)malloc(2);
			strcpy(key->value,"2");
			key->required = TRUE;
			key = create_FITS_keyword("NAXIS1",object);
			strcpy(key->type,"INTEGER");
			key->required = TRUE;
			key = create_FITS_keyword("NAXIS2",object);
			strcpy(key->type,"INTEGER");
			key->required = TRUE;
			key = create_FITS_keyword("PCOUNT",object);
			strcpy(key->type,"INTEGER");
			key->required = TRUE;
			key = create_FITS_keyword("GCOUNT",object);
			strcpy(key->type,"INTEGER");
			key->required = TRUE;
		}
		if (strcmp(object->name,"TABLE") == 0) {
			key = create_FITS_keyword("XTENSION",object);
			strcpy(key->type,"CHARACTER");
			key->value = (char *)malloc(12);
			strcpy(key->value,"'TABLE   '");
			key->required = TRUE;
			key = create_FITS_keyword("BITPIX",object);
			strcpy(key->type,"INTEGER");
			key->value = (char *)malloc(2);
			strcpy(key->value,"8");
			key->required = TRUE;
			key = create_FITS_keyword("NAXIS",object);
			strcpy(key->type,"INTEGER");
			key->value = (char *)malloc(2);
			strcpy(key->value,"2");
			key->required = TRUE;
			key = create_FITS_keyword("NAXIS1",object);
			strcpy(key->type,"INTEGER");
			key->required = TRUE;
			key = create_FITS_keyword("NAXIS2",object);
			strcpy(key->type,"INTEGER");
			key->required = TRUE;
			key = create_FITS_keyword("PCOUNT",object);
			strcpy(key->type,"INTEGER");
			key->value = (char *)malloc(2);
			strcpy(key->value,"0");
			key->required = TRUE;
			key = create_FITS_keyword("GCOUNT",object);
			strcpy(key->type,"INTEGER");
			key->value = (char *)malloc(2);
			strcpy(key->value,"1");
			key->required = TRUE;
			key = create_FITS_keyword("TFIELDS",object);
			strcpy(key->type,"INTEGER");
			key->required = TRUE;
		}
		if (strcmp(object->name,"BINTABLE") == 0){
			key = create_FITS_keyword("XTENSION",object);
			strcpy(key->type,"CHARACTER");
			key->value = (char *)malloc(12);
			strcpy(key->value,"'BINTABLE'");
			key->required = TRUE;
			key = create_FITS_keyword("BITPIX",object);
			strcpy(key->type,"INTEGER");
			key->value = (char *)malloc(2);
			strcpy(key->value,"8");
			key->required = TRUE;
			key = create_FITS_keyword("NAXIS",object);
			strcpy(key->type,"INTEGER");
			key->value = (char *)malloc(2);
			strcpy(key->value,"2");
			key->required = TRUE;
			key = create_FITS_keyword("NAXIS1",object);
			strcpy(key->type,"INTEGER");
			key->required = TRUE;
			key = create_FITS_keyword("NAXIS2",object);
			strcpy(key->type,"INTEGER");
			key->required = TRUE;
			key = create_FITS_keyword("PCOUNT",object);
			strcpy(key->type,"INTEGER");
         key->value = (char *)malloc(2);
			strcpy(key->value,"0");
			key->required = TRUE;
			key = create_FITS_keyword("GCOUNT",object);
			strcpy(key->type,"INTEGER");
			key->value = (char *)malloc(2);
			strcpy(key->value,"1");
			key->required = TRUE;
			key = create_FITS_keyword("TFIELDS",object);
			strcpy(key->type,"INTEGER");
			key->required = TRUE;
		}
	}
	return  OK;
}  /* add required_keys */


/*****************************************************************************
* Function: create_FITS_keyword
* Abstract: Routine to create a new FITS keyword and link it onto the end of
*				the current list of the parent object
* Description:
* Input
*          keyword: Char string of FITS keyword name
*			  parent:  pointer to FITS object
* Return:
*	        pointer to new FITS keyword object
******************************************************************************/
FITS_keyword *create_FITS_keyword(char *keyword, FITS_object *parent)
{
	FITS_keyword *new_keyword; /* new keyword object */
	FITS_keyword *searchkey;   /* used for traversing keyword list */

/* allocate space for new keyword */
	new_keyword = (FITS_keyword *)malloc(sizeof(FITS_keyword));
/* initialize newkeyword to default values */
	strcpy(new_keyword->name,keyword);
	new_keyword->value = NULL;
	new_keyword->required = FALSE;
	new_keyword->next  = NULL;

/* link keyword onto end of parent keyword list: */
	if (parent->keyword_list == NULL){
		parent->keyword_list = new_keyword;
		new_keyword->prev  = NULL;
	}
	else {
		searchkey = parent->keyword_list;
		while (searchkey->next != NULL) searchkey = searchkey->next;
		searchkey->next = new_keyword;
		new_keyword->prev = searchkey;
	}
	parent->keyword_cnt++;

	return new_keyword;
} /* end  create_FITS_keyword */