#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <math.h>

#include "amdmsFits.h"

amdmsBOOL amdmsReadKeywordInt(amdmsFITS *file, char *name, int *value, char *comment)
{
  int status = 0;

  if (file == NULL) {
    return amdmsFALSE;
  }
  if (file->currStateFile != amdmsFILE_OPENED_STATE) {
    amdmsError(__FILE__, __LINE__,
	      "amdmsReadKeywordInt(%s, %s, .., ..), no open file!", file->fileName, name);
    return amdmsFALSE;
  }
  if (fits_read_key(file->fits, TINT, name, value, comment, &status) != 0) {
    if (status != VALUE_UNDEFINED && status != KEY_NO_EXIST) {
      amdmsReportFitsError(file, status, __LINE__, name);
    }
    amdmsDebug(__FILE__, __LINE__,
	      "amdmsReadKeywordInt(%s, %s, .., ..): keyword not found", file->fileName, name);
    return amdmsFALSE;
  }
  amdmsDebug(__FILE__, __LINE__,
	     "amdmsReadKeywordInt(%s, %s, .., ..) = %d", file->fileName, name, *value);
  return amdmsTRUE;
}

amdmsBOOL amdmsReadKeywordLong(amdmsFITS *file, char *name, long *value, char *comment)
{
  int status = 0;

  if (file == NULL) {
    return amdmsFALSE;
  }
  if (file->currStateFile != amdmsFILE_OPENED_STATE) {
    amdmsError(__FILE__, __LINE__,
	      "amdmsReadKeywordLong(%s, %s, .., ..), no open file!", file->fileName, name);
    return amdmsFALSE;
  }
  if (fits_read_key_lng(file->fits, name, value, comment, &status) != 0) {
    if (status != VALUE_UNDEFINED && status != KEY_NO_EXIST) {
      amdmsReportFitsError(file, status, __LINE__, name);
    }
    amdmsDebug(__FILE__, __LINE__,
	      "amdmsReadKeywordLong(%s, %s, .., ..): keyword not found", file->fileName, name);
    return amdmsFALSE;
  }
  amdmsDebug(__FILE__, __LINE__,
	     "amdmsReadKeywordLong(%s, %s, .., ..) = %d", file->fileName, name, *value);
  return amdmsTRUE;
}

amdmsBOOL amdmsReadKeywordFloat(amdmsFITS *file, char *name, float *value, char *comment)
{
  int status = 0;

  if (file == NULL) {
    return amdmsFALSE;
  }
  if (file->currStateFile != amdmsFILE_OPENED_STATE) {
    amdmsError(__FILE__, __LINE__,
	      "amdmsReadKeywordFloat(%s, %s, .., ..), no open file!", file->fileName, name);
    return amdmsFALSE;
  }
  if (fits_read_key_flt(file->fits, name, value, comment, &status) != 0) {
    if (status != VALUE_UNDEFINED && status != KEY_NO_EXIST) {
      amdmsReportFitsError(file, status, __LINE__, name);
    }
    amdmsDebug(__FILE__, __LINE__,
	      "amdmsReadKeywordFloat(%s, %s, .., ..): keyword not found", file->fileName, name);
    return amdmsFALSE;
  }
  amdmsDebug(__FILE__, __LINE__,
	     "amdmsReadKeywordFloat(%s, %s, .., ..) = %f", file->fileName, name, *value);
  return amdmsTRUE;
}

amdmsBOOL amdmsReadKeywordDouble(amdmsFITS *file, char *name, double *value, char *comment)
{
  int status = 0;

  if (file == NULL) {
    return amdmsFALSE;
  }
  if (file->currStateFile != amdmsFILE_OPENED_STATE) {
    amdmsError(__FILE__, __LINE__,
	      "amdmsReadKeywordDouble(%s, %S, .., ..), no open file!", file->fileName, name);
    return amdmsFALSE;
  }
  if (fits_read_key_dbl(file->fits, name, value, comment, &status) != 0) {
    if (status != VALUE_UNDEFINED && status != KEY_NO_EXIST) {
      amdmsReportFitsError(file, status, __LINE__, name);
    }
    amdmsDebug(__FILE__, __LINE__,
	      "amdmsReadKeywordDouble(%s, %S, .., ..): keyword not found", file->fileName, name);
    return amdmsFALSE;
  }
  amdmsDebug(__FILE__, __LINE__,
	     "amdmsReadKeywordDouble(%s, %s, .., ..) = %f", file->fileName, name, *value);
  return amdmsTRUE;
}

amdmsBOOL amdmsReadKeywordString(amdmsFITS *file, char *name, char *value, char *comment)
{
  int status = 0;

  if (file == NULL) {
    return amdmsFALSE;
  }
  if (file->currStateFile != amdmsFILE_OPENED_STATE) {
    amdmsError(__FILE__, __LINE__,
	      "amdmsReadKeywordString(%s, %S, .., ..), no open file!", file->fileName, name);
    return amdmsFALSE;
  }
  if (fits_read_key_str(file->fits, name, value, comment, &status) != 0) {
    if (status != VALUE_UNDEFINED && status != KEY_NO_EXIST) {
      amdmsReportFitsError(file, status, __LINE__, name);
    }
    amdmsDebug(__FILE__, __LINE__,
	      "amdmsReadKeywordString(%s, %S, .., ..): keyword not found", file->fileName, name);
    return amdmsFALSE;
  }
  amdmsDebug(__FILE__, __LINE__,
	     "amdmsReadKeywordString(%s, %s, .., ..) = %s", file->fileName, name, value);
  return amdmsTRUE;
}

amdmsKEYWORD *amdmsAppendKeyword(amdmsFITS *file, char *name, int type, char *comment)
{
  amdmsKEYWORD *kwd;
  amdmsKEYWORD *hkwd;

  kwd = (amdmsKEYWORD *)calloc(1L, sizeof(amdmsKEYWORD));
  if (kwd == NULL) {
    return NULL;
  }
  kwd->next = NULL;
  if (file->hdrKeys == NULL) {
    file->hdrKeys = kwd;
  } else {
    hkwd = file->hdrKeys;
    while (hkwd->next != NULL) {
      hkwd = hkwd->next;
    }
    hkwd->next = kwd;
  }
  strcpy(kwd->name, name);
  kwd->type = type;
  if (comment != NULL) {
    strcpy(kwd->comment, comment);
  } else {
    kwd->comment[0] = '\0';
  }
  return kwd;
}

amdmsCOMPL amdmsUpdateKeywordInt(amdmsFITS *file, char *name, int value, char *comment)
{
  amdmsKEYWORD *kwd;

  kwd = amdmsAppendKeyword(file, name, TINT, comment);
  if (kwd == NULL) {
    return amdmsFAILURE;
  }
  kwd->longValue = (long)value;
  return amdmsSUCCESS;
}

amdmsCOMPL amdmsUpdateKeywordLong(amdmsFITS *file, char *name, long value, char *comment)
{
  amdmsKEYWORD *kwd;

  kwd = amdmsAppendKeyword(file, name, TLONG, comment);
  if (kwd == NULL) {
    return amdmsFAILURE;
  }
  kwd->longValue = value;
  return amdmsSUCCESS;
}

amdmsCOMPL amdmsUpdateKeywordFloat(amdmsFITS *file, char *name, float value, int decimals, char *comment)
{
  amdmsKEYWORD *kwd;

  kwd = amdmsAppendKeyword(file, name, TFLOAT, comment);
  if (kwd == NULL) {
    return amdmsFAILURE;
  }
  kwd->decimals = decimals;
  kwd->doubleValue = (double)value;
  return amdmsSUCCESS;
}

amdmsCOMPL amdmsUpdateKeywordDouble(amdmsFITS *file, char *name, double value, int decimals, char *comment)
{
  amdmsKEYWORD *kwd;

  kwd = amdmsAppendKeyword(file, name, TDOUBLE, comment);
  if (kwd == NULL) {
    return amdmsFAILURE;
  }
  kwd->decimals = decimals;
  kwd->doubleValue = value;
  return amdmsSUCCESS;
}

amdmsCOMPL amdmsUpdateKeywordString(amdmsFITS *file, char *name, char *value, char *comment)
{
  amdmsKEYWORD *kwd;

  kwd = amdmsAppendKeyword(file, name, TSTRING, comment);
  if (kwd == NULL) {
    return amdmsFAILURE;
  }
  strcpy(kwd->stringValue, value);
  return amdmsSUCCESS;
}

amdmsCOMPL amdmsUpdateKeywords(amdmsFITS *file)
{
  int          status = 0;
  amdmsKEYWORD *kwd;

  amdmsDebug(__FILE__, __LINE__, "ENTER amdmsUpdateKeywords(%s)", file->fileName);
  if (file->currStateFile != amdmsFILE_CREATED_STATE) {
    /* amdmsVBF(amdmsVERBOSE_ERROR, (stderr, "ERROR: amdmsFITS::UpdateKeywords(), no open file!\n")); */
    return amdmsFAILURE;
  }
  while (file->hdrKeys != NULL) {
    kwd = file->hdrKeys;
    amdmsDebug(__FILE__, __LINE__, "  updating %s", kwd->name);
    switch (kwd->type) {
    case TINT:
    case TLONG:
      if (fits_update_key_lng(file->fits, kwd->name, kwd->longValue, kwd->comment, &status) != 0) {
	amdmsReportFitsError(file, status, __LINE__, kwd->name);
	return amdmsFAILURE;
      }
      break;
    case TFLOAT:
      if (fits_update_key_flt(file->fits, kwd->name, (float)(kwd->doubleValue), kwd->decimals, kwd->comment, &status) != 0) {
	amdmsReportFitsError(file, status, __LINE__, kwd->name);
	return amdmsFAILURE;
      }
      break;
    case TDOUBLE:
      if (fits_update_key_dbl(file->fits, kwd->name, kwd->doubleValue, kwd->decimals, kwd->comment, &status) != 0) {
	amdmsReportFitsError(file, status, __LINE__, kwd->name);
	return amdmsFAILURE;
      }
      break;
    case TSTRING:
      if (fits_update_key_str(file->fits, kwd->name, kwd->stringValue, kwd->comment, &status) != 0) {
	amdmsReportFitsError(file, status, __LINE__, kwd->name);
	return amdmsFAILURE;
      }
      break;
    default:;
    }
    file->hdrKeys = file->hdrKeys->next;
    free(kwd);
  }
  amdmsDebug(__FILE__, __LINE__, "LEAVE amdmsUpdateKeywords(%s)", file->fileName);
  return amdmsSUCCESS;
}

