/******************************************************************************
 * $Id$
 *
 * Project:  ASI CEOS Translator
 * Purpose:  CEOS library prototypes
 * Author:   Paul Lahaie, pjlahaie@atlsci.com
 *
 ******************************************************************************
 * Copyright (c) 2000, Atlantis Scientific Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 ****************************************************************************/

#ifndef CEOS_H
#define CEOS_H

#include "cpl_conv.h"

CPL_C_START

#define int32 GInt32
#define TBool int
#define uchar unsigned char

typedef struct Link_t_struct
{
    struct Link_t_struct *next;
    void *object;
} Link_t;

#define HMalloc CPLMalloc
#define HFree CPLFree
#define HCalloc CPLCalloc

Link_t *ceos2CreateLink(void *pObject);
Link_t *InsertLink(Link_t *psList, Link_t *psLink);
void DestroyList(Link_t *psList);
Link_t *AddLink(Link_t *psList, Link_t *psLink);

/* Basic CEOS header defs */

#define SEQUENCE_OFF 0
#define TYPE_OFF 4
#define LENGTH_OFF 8
#define CEOS_HEADER_LENGTH 12

/* Defines for CEOS banding type */

#define CEOS_IL_PIXEL 1
#define CEOS_IL_LINE 2
#define CEOS_IL_BAND 3

/* Defines for CEOS data types */

#define CEOS_TYP_CHAR 1
#define CEOS_TYP_UCHAR 2
#define CEOS_TYP_SHORT 3
#define CEOS_TYP_USHORT 4
#define CEOS_TYP_LONG 5
#define CEOS_TYP_ULONG 6
#define CEOS_TYP_FLOAT 7
#define CEOS_TYP_DOUBLE 8
#define CEOS_TYP_COMPLEX_CHAR 9
#define CEOS_TYP_COMPLEX_UCHAR 10
#define CEOS_TYP_COMPLEX_SHORT 11
#define CEOS_TYP_COMPLEX_USHORT 12
#define CEOS_TYP_COMPLEX_LONG 13
#define CEOS_TYP_COMPLEX_ULONG 14
#define CEOS_TYP_COMPLEX_FLOAT 15
#define CEOS_TYP_CCP_COMPLEX_FLOAT 16    /* COMPRESSED CROSS PRODUCT */
#define CEOS_TYP_PALSAR_COMPLEX_SHORT 17 /* PALSAR - treat as COMPLEX SHORT*/

/* Defines for CEOS file names */

#define CEOS_VOLUME_DIR_FILE 0
#define CEOS_LEADER_FILE 1
#define CEOS_IMAGRY_OPT_FILE 2
#define CEOS_TRAILER_FILE 3
#define CEOS_NULL_VOL_FILE 4
#define CEOS_ANY_FILE -1

/* Defines for Recipe values */

#define CEOS_REC_NUMCHANS 1
#define CEOS_REC_INTERLEAVE 2
#define CEOS_REC_DATATYPE 3
#define CEOS_REC_BPR 4
#define CEOS_REC_LINES 5
#define CEOS_REC_TBP 6
#define CEOS_REC_BBP 7
#define CEOS_REC_PPL 8
#define CEOS_REC_LBP 9
#define CEOS_REC_RBP 10
#define CEOS_REC_BPP 11
#define CEOS_REC_RPL 12
#define CEOS_REC_PPR 13
#define CEOS_REC_IDS 14
#define CEOS_REC_FDL 15
#define CEOS_REC_PIXORD 16
#define CEOS_REC_LINORD 17
#define CEOS_REC_PRODTYPE 18
#define CEOS_REC_RECORDSIZE 19
#define CEOS_REC_SUFFIX_SIZE 20
#define CEOS_REC_PDBPR 21

/* Defines for Recipe Types */

#define CEOS_REC_TYP_A 1
#define CEOS_REC_TYP_B 2
#define CEOS_REC_TYP_I 3

/* Defines for SAR Embedded info */

#define CEOS_SAR_ACQ_YEAR 1
#define CEOS_SAR_ACQ_DAY 2
#define CEOS_SAR_ACQ_MSEC 4
#define CEOS_SAR_TRANS_POL 8
#define CEOS_SAR_PULSE_REP 16
#define CEOS_SAR_SLANT_FIRST 32
#define CEOS_SAR_SLANT_MID 64
#define CEOS_SAR_SLANT_LAST 128

/* Maximum size of LUT for Calibration records */
#define CEOS_RADAR_MAX_LUT 512
#define CEOS_RADAR_FLIP_DATE 19980101
#define CEOS_RADAR_FACILITY "CDPF-RSAT"

/* Defines for GCP Ordering mode */
#define CEOS_STD_MAPREC_GCP_ORDER 0
#define CEOS_ASF_MAPREC_GCP_ORDER 1
#define CEOS_ASF_FACREC_GCP_ORDER 2

typedef union
{
    int32 Int32Code;

    struct
    {
        uchar Subtype1;
        uchar Type;
        uchar Subtype2;
        uchar Subtype3;
    } UCharCode;
} CeosTypeCode_t;

typedef struct
{
    int32 Sequence;
    CeosTypeCode_t TypeCode;
    int32 Length;
    int32 Flavor;
    int32 Subsequence;
    int32 FileId;
    uchar *Buffer;
} CeosRecord_t;

struct CeosSARImageDesc
{
    TBool ImageDescValid;
    int NumChannels;
    int32 ChannelInterleaving;
    int32 DataType;
    int BytesPerRecord;
    int Lines;
    int TopBorderPixels;
    int BottomBorderPixels;
    int PixelsPerLine;
    int LeftBorderPixels;
    int RightBorderPixels;
    int BytesPerPixel;
    int RecordsPerLine;
    int PixelsPerRecord;
    int ImageDataStart;
    int ImageSuffixData;
    int FileDescriptorLength;
    int32 PixelOrder;
    int32 LineOrder;
    int PixelDataBytesPerRecord;
};

typedef struct
{
    int32 Flavor;
    int32 Sensor;
    int32 ProductType;
    int32 FileNamingConvention;
    TBool VolumeDirectoryFile;
    TBool SARLeaderFile;
    TBool ImagryOptionsFile;
    TBool SARTrailerFile;
    TBool NullVolumeDirectoryFile;

    struct CeosSARImageDesc ImageDesc;

    Link_t *RecordList;
} CeosSARVolume_t;

typedef struct
{
    int ImageDescValue;
    int Override;
    int FileId;

    struct
    {
        unsigned char Subtype1, Type, Subtype2, Subtype3;
    } TypeCode;

    int Offset;
    int Length;
    int Type;
} CeosRecipeType_t;

typedef struct
{
    CeosRecipeType_t *Recipe;
} CeosSARImageDescRecipe_t;

typedef struct
{
    int32 ValidFields;
    TBool SensorUpdate;
    int32 AcquisitionYear;
    int32 AcquisitionDay;
    int32 AcquisitionMsec;
    int32 TransmittedPolarization;
    int32 ReceivedPolarization;
    int32 PulseRepetitionFrequency;
    int32 SlantRangeFirstPixel;
    int32 SlantRangeMidPixel;
    int32 SlantRangeLastPixel;
} CeosSAREmbeddedInfo_t;

typedef struct
{
    double Slant[6];
    double Lut[512];
    double SemiMajorAxis;
    double PlatformLatitude;
    double CalibrationScale;
    int NumberOfSamples;
    int Increment;
    TBool PossiblyFlipped;
} CeosRadarCalibration_t;

/* Function prototypes */

void InitEmptyCeosRecord(CeosRecord_t *record, int32 sequence,
                         CeosTypeCode_t typecode, int32 length);

void InitCeosRecord(CeosRecord_t *record, uchar *buffer);

void InitCeosRecordWithHeader(CeosRecord_t *record, uchar *header,
                              uchar *buffer);

int DetermineCeosRecordBodyLength(const uchar *header);

void DeleteCeosRecord(CeosRecord_t *record);

void GetCeosRecordStruct(const CeosRecord_t *record, void *struct_ptr);

void PutCeosRecordStruct(CeosRecord_t *record, const void *struct_ptr);

void GetCeosField(CeosRecord_t *, int32, const char *, void *);

void SetCeosField(CeosRecord_t *record, int32 start_byte, const char *format,
                  int intValue, double dblValue);

void SetIntCeosField(CeosRecord_t *record, int32 start_byte, int32 length,
                     int32 value);

CeosRecord_t *FindCeosRecord(Link_t *record_list, CeosTypeCode_t typecode,
                             int32 fileid, int32 flavor, int32 subsequence);

void SerializeCeosRecordsToFile(Link_t *record_list, VSILFILE *fp);

void SerializeCeosRecordsFromFile(Link_t *record_list, VSILFILE *fp);

void InitCeosSARVolume(CeosSARVolume_t *volume, int32 file_name_convention);

void GetCeosSARImageDesc(CeosSARVolume_t *volume);

void GetCeosSARImageDescInfo(CeosSARVolume_t *volume,
                             CeosSARImageDescRecipe_t *recipe);

void CalcCeosSARImageFilePosition(CeosSARVolume_t *volume, int channel,
                                  int line, int *record, int *file_offset);

int32 GetCeosSARImageData(CeosSARVolume_t *volume,
                          CeosRecord_t *processed_data_record, int channel,
                          int xoff, int xsize, int bufsize, uchar *buffer);

void DetermineCeosSARPixelOrder(CeosSARVolume_t *volume, CeosRecord_t *record);

void GetCeosSAREmbeddedInfo(CeosSARVolume_t *volume,
                            CeosRecord_t *processed_data_record,
                            CeosSAREmbeddedInfo_t *info);

void DeleteCeosSARVolume(CeosSARVolume_t *volume);

void RegisterRecipes(void);
void FreeRecipes(void);

void AddRecipe(int (*function)(CeosSARVolume_t *volume, const void *token),
               const void *token, const char *name);

int CeosDefaultRecipe(CeosSARVolume_t *volume, const void *token);
int ScanSARRecipeFCN(CeosSARVolume_t *volume, const void *token);

/* ceoscalib.c function declarations */

CeosRadarCalibration_t *GetCeosRadarCalibration(CeosSARVolume_t *volume);

/* CEOS byte swapping stuff */

#if defined(CPL_MSB)
#define NativeToCeos(a, b, c, d) memcpy(a, b, c)
#define CeosToNative(a, b, c, d) memcpy(a, b, c)
#else
void NativeToCeos(void *dst, const void *src, const size_t len,
                  const size_t swap_unit);
#define CeosToNative(a, b, c, d) NativeToCeos(a, b, c, d)
#endif

/* Recipe defines */

CPL_C_END

#endif
