/*                                                                           *
 *   This file is part of the SINFONI   Pipeline                             *
 *   Copyright (C) 2002,2003 European Southern Observatory                   *
 *                                                                           *
 *   This library is free software; you can redistribute it and/or modify    *
 *   it under the terms of the GNU General Public License as published by    *
 *   the Free Software Foundation; either version 2 of the License, or       *
 *   (at your option) any later version.                                     *
 *                                                                           *
 *   This program is distributed in the hope that it will be useful,         *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
 *   GNU General Public License for more details.                            *
 *                                                                           *
 *   You should have received a copy of the GNU General Public License       *
 *   along with this program; if not, write to the Free Software             *
 *   Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA    *
 *                                                                           */

/*
 * $Author: amodigli $
 * $Date: 2012/09/21 10:55:19 $
 * $Revision: 1.9 $
 * $Name: sinfo-2_4_0 $
 * $Log: sinfo_dump.c,v $
 * Revision 1.9  2012/09/21 10:55:19  amodigli
 * removed warning from clang
 *
 * Revision 1.8  2012/03/02 08:42:20  amodigli
 * fixed some typos on doxygen
 *
 * Revision 1.7  2011/11/23 17:29:19  amodigli
 * fix warning with cpl6
 *
 * Revision 1.6  2008/01/17 07:54:04  amodigli
 * shorten long lines
 *
 * Revision 1.5  2007/08/11 10:45:47  amodigli
 * upgrade to CPL4, fixed compil warnings
 *
 * Revision 1.4  2007/06/06 07:10:45  amodigli
 * replaced tab with 4 spaces
 *
 * Revision 1.3  2006/10/20 08:07:05  amodigli
 * using prefix sinfo_ in place of sinfoni_ for includes
 *
 * Revision 1.2  2006/10/16 07:26:23  amodigli
 * shortened line length
 *
 * Revision 1.1  2006/08/09 12:20:11  amodigli
 * added sinfo_dump.h sinfo_dump.c
 *
 * Revision 1.7  2006/05/12 15:02:05  jmlarsen
 * Support NULL tags
 *
 * Revision 1.6  2006/02/28 09:15:22  jmlarsen
 * Minor update
 *
 * Revision 1.5  2006/02/15 13:19:15  jmlarsen
 * Reduced source code max. line length
 *
 * Revision 1.4  2005/12/19 16:17:56  jmlarsen
 * Replaced bool -> int
 *
 */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

/**@{*/

/*----------------------------------------------------------------------------*/
/**
   @defgroup sinfo_dump  Print CPL objects

   Functions that enables dumping (using CPL's messaging system) some
   otherwise non-dumpable CPL objects
 */
/*----------------------------------------------------------------------------*/


#include <sinfo_dump.h>
#include <sinfo_utils.h>
#include <sinfo_error.h>
#include <sinfo_msg.h>
#include <cpl.h>

/*----------------------------------------------------------------*/
/** 
 * @brief Print a property list.
 * @param pl      The property list to print.
 * @param low     Index of first property to print.
 * @param high    Index of first property not to print.
 * @return CPL_ERROR_NONE iff OK.
 *
 * This function prints all properties in the property list @em pl
 * in the range from @em low (included) to @em high (not included)
 * counting from zero.
 */
/*----------------------------------------------------------------*/
cpl_error_code
sinfo_print_cpl_propertylist(const cpl_propertylist *pl, long low, long high)
{
    cpl_property *prop;
    long i = 0;
    
    assure (0 <= low && high <= cpl_propertylist_get_size(pl) && low <= high,
        CPL_ERROR_ILLEGAL_INPUT, "Illegal range");
    /* Printing an empty range is allowed but only when low == high */

    if (pl == NULL){
    sinfo_msg("NULL");
    }
    else if (cpl_propertylist_is_empty(pl))  {
    sinfo_msg("[Empty property list]");
    }
    else    
    for (i = low; i < high; i++)
        {
        /* bug workaround: remove const cast when declaration 
           of cpl_propertylist_get() is changed */
        prop = cpl_propertylist_get((cpl_propertylist *)pl, i);
        check (sinfo_print_cpl_property(prop), 
                "Error printing property");
        }
    
  cleanup:
    return cpl_error_get_code();
}
/*----------------------------------------------------------------*/
/** 
 * @brief Print a property.
 * @param prop      The property to print.
 * @return CPL_ERROR_NONE iff OK.
 *
 * This function prints a property's name, value and comment.
 */
/*----------------------------------------------------------------*/

cpl_error_code
sinfo_print_cpl_property(const cpl_property *prop)
{
    cpl_type t;

    if (prop == NULL)
    {
        sinfo_msg("NULL");
    }
    else
    {   
        /* print property with this formatting
           NAME =
             VALUE
           COMMENT
        */

        /* print name */
        
        sinfo_msg("%s =", cpl_property_get_name(prop));

        /* print value */
        
        check( t = cpl_property_get_type(prop), 
                  "Could not read property type");
        
        switch(t & (~CPL_TYPE_FLAG_ARRAY))
        {
        case CPL_TYPE_CHAR:
            if (t & CPL_TYPE_FLAG_ARRAY)  /* if type is string */
            {
                sinfo_msg("  '%s'", cpl_property_get_string(prop));
            }
            else                          /* an ordinary char */
            {
                sinfo_msg("  %c", cpl_property_get_char(prop));
            }
            break;
        case CPL_TYPE_BOOL:    if (cpl_property_get_bool(prop))
            {sinfo_msg("  true");}
        else
            {sinfo_msg("  false");}
            break;
        case CPL_TYPE_UCHAR: 
	  sinfo_msg("%c",cpl_property_get_char(prop)); 
          break;
        case CPL_TYPE_INT:   
	  sinfo_msg("%d",cpl_property_get_int(prop)); 
          break;
        case CPL_TYPE_UINT:  
          sinfo_msg("%d",cpl_property_get_int(prop)); 
          break;
        case CPL_TYPE_LONG: 
          sinfo_msg("%ld",cpl_property_get_long(prop)); 
          break;
        case CPL_TYPE_ULONG: 
          sinfo_msg("%ld",cpl_property_get_long(prop)); 
          break;
        case CPL_TYPE_FLOAT: 
          sinfo_msg("%f",cpl_property_get_float(prop)); 
          break;
        case CPL_TYPE_DOUBLE: 
          sinfo_msg("%f",cpl_property_get_double(prop)); 
          break;
        case CPL_TYPE_POINTER: 
          sinfo_msg("POINTER");    
          break;
        case CPL_TYPE_INVALID: 
          sinfo_msg("INVALID");    
          break;
        default: 
          sinfo_msg("  unrecognized property");  
          break;
        }
        
        /* Is this property an array? */
        if (t & CPL_TYPE_FLAG_ARRAY){
           cpl_msg_info(cpl_func,"  (array size = %" CPL_SIZE_FORMAT " )", 
              cpl_property_get_size(prop));
        }

        /* Print comment */
        if (cpl_property_get_comment(prop) != NULL){
        sinfo_msg("    %s", cpl_property_get_comment(prop));
        }
    }

  cleanup:
    return cpl_error_get_code();
}

/*----------------------------------------------------------------*/
/** 
 * @brief Print a frame set
 * @param frames Frame set to print
 * @return CPL_ERROR_NONE iff OK.
 *
 * This function prints all frames in a CPL frame set.
 */
/*----------------------------------------------------------------*/
cpl_error_code
sinfo_print_cpl_frameset(const cpl_frameset *frames)
{
    /* Two special cases: a NULL frame set and an empty frame set */

    if (frames == NULL)
    {
        sinfo_msg("NULL");
    }
    else
    {
        const cpl_frame *f = NULL;
        check( f = cpl_frameset_get_first_const(frames), 
                   "Error reading frameset");
        
        if (f == NULL)
        {
            sinfo_msg("[Empty frame set]");
        }
        else
        {
            while(f != NULL)
            {
                check( sinfo_print_cpl_frame(f), 
                                  "Could not print frame");
                check( f = cpl_frameset_get_next_const(frames), 
                                  "Error reading frameset");
            }
        }
    }
    
  cleanup:
    return cpl_error_get_code();
}

/*----------------------------------------------------------------*/
/** 
 * @brief Print a frame
 * @param f Frame to print
 * @return CPL_ERROR_NONE iff OK.
 *
 * This function prints a CPL frame.
 */
/*----------------------------------------------------------------*/
cpl_error_code
sinfo_print_cpl_frame(const cpl_frame *f)
{
    if (f == NULL)
    {
        sinfo_msg("NULL");
    }
    else
    {
        sinfo_msg("%-7s %-20s '%s'", 
             sinfo_tostring_cpl_frame_group(cpl_frame_get_group(f)),
             cpl_frame_get_tag(f) != NULL ? 
                     cpl_frame_get_tag(f) : "Null",
             cpl_frame_get_filename(f));
        
        sinfo_msg_debug("type \t= %s",   
            sinfo_tostring_cpl_frame_type (cpl_frame_get_type (f)));
        sinfo_msg_debug("group \t= %s",  
            sinfo_tostring_cpl_frame_group(cpl_frame_get_group(f)));
        sinfo_msg_debug("level \t= %s",  
            sinfo_tostring_cpl_frame_level(cpl_frame_get_level(f)));
    }

    return cpl_error_get_code();
}

/*----------------------------------------------------------------*/
/** 
 * @brief Convert a frame type to a string
 * @param ft  Frame type to convert
 * @return A textual representation of @em  ft.
 */
/*----------------------------------------------------------------*/
const char *
sinfo_tostring_cpl_frame_type(cpl_frame_type ft)
{    
    switch(ft)
    {
    case CPL_FRAME_TYPE_NONE:   return "NONE";
    case CPL_FRAME_TYPE_IMAGE:  return "IMAGE";
    case CPL_FRAME_TYPE_MATRIX: return "MATRIX";
    case CPL_FRAME_TYPE_TABLE:  return "TABLE";
    default: return "unrecognized frame type";
    }
}

/*----------------------------------------------------------------*/
/** 
 * @brief Convert a frame group to a string
 * @param fg  Frame group to convert
 * @return A textual representation of @em  fg.
 */
/*----------------------------------------------------------------*/
const char *
sinfo_tostring_cpl_frame_group(cpl_frame_group fg)
{
    switch(fg)
    {
    case CPL_FRAME_GROUP_NONE:    return "NONE";
    case CPL_FRAME_GROUP_RAW:     return CPL_FRAME_GROUP_RAW_ID;
    case CPL_FRAME_GROUP_CALIB:   return CPL_FRAME_GROUP_CALIB_ID;
    case CPL_FRAME_GROUP_PRODUCT: return CPL_FRAME_GROUP_PRODUCT_ID;
    default:
        return "unrecognized frame group";
    }
}

/*----------------------------------------------------------------*/
/** 
 * @brief Convert a frame level to a string
 * @param fl  Frame level to convert
 * @return A textual representation of @em  fl.
 */
/*----------------------------------------------------------------*/
const char *
sinfo_tostring_cpl_frame_level(cpl_frame_level fl)
{
    
    switch(fl)
    {
    case CPL_FRAME_LEVEL_NONE:        return "NONE";
    case CPL_FRAME_LEVEL_TEMPORARY:   return "TEMPORARY";
    case CPL_FRAME_LEVEL_INTERMEDIATE:return "INTERMEDIATE";
    case CPL_FRAME_LEVEL_FINAL:       return "FINAL";
    default: return "unrecognized frame level";
    }
}


/*----------------------------------------------------------------*/
/** 
 * @brief Convert a CPL type to a string
 * @param t  Type to convert
 * @return A textual representation of @em  t.
 */
/*----------------------------------------------------------------*/
const char *
sinfo_tostring_cpl_type(cpl_type t)
{

    /* Note that CPL_TYPE_STRING is shorthand
       for CPL_TYPE_CHAR | CPL_TYPE_FLAG_ARRAY . */

    if (!(t & CPL_TYPE_FLAG_ARRAY))
    switch(t & (~CPL_TYPE_FLAG_ARRAY))
        {
        case CPL_TYPE_CHAR:       return "char";
        case CPL_TYPE_UCHAR:      return "uchar";
        case CPL_TYPE_BOOL:       return "boolean";
        case CPL_TYPE_INT:        return "int";
        case CPL_TYPE_UINT:       return "uint";
        case CPL_TYPE_LONG:       return "long";
        case CPL_TYPE_ULONG:      return "ulong";
        case CPL_TYPE_FLOAT:      return "float";
        case CPL_TYPE_DOUBLE:     return "double";
        case CPL_TYPE_POINTER:    return "pointer";
/* not in CPL3.0: case CPL_TYPE_COMPLEX:    return "complex"; */
        case CPL_TYPE_INVALID:    return "invalid";
        default:
        return "unrecognized type";
        }
    else
    switch(t & (~CPL_TYPE_FLAG_ARRAY))
        {
        case CPL_TYPE_CHAR:       return "string (char array)";
        case CPL_TYPE_UCHAR:      return "uchar array";
        case CPL_TYPE_BOOL:       return "boolean array";
        case CPL_TYPE_INT:        return "int array";
        case CPL_TYPE_UINT:       return "uint array";
        case CPL_TYPE_LONG:       return "long array";
        case CPL_TYPE_ULONG:      return "ulong array";
        case CPL_TYPE_FLOAT:      return "float array";
        case CPL_TYPE_DOUBLE:     return "double array";
        case CPL_TYPE_POINTER:    return "pointer array";
/* not in CPL3.0: case CPL_TYPE_COMPLEX:    return "complex array"; */
        case CPL_TYPE_INVALID:    return "invalid (array)";
        default:
        return "unrecognized type";
        }
}
/**@}*/
