/******************************************************************************
 *
 * Project:  DTED Translator
 * Purpose:  Public (C callable) interface for DTED/CDED reading.
 * Author:   Frank Warmerdam, warmerdam@pobox.com
 *
 ******************************************************************************
 * Copyright (c) 1999, Frank Warmerdam
 * Copyright (c) 2007-2012, Even Rouault <even dot rouault at spatialys.com>
 *
 * SPDX-License-Identifier: MIT
 ****************************************************************************/

#ifndef DTED_API_H_INCLUDED
#define DTED_API_H_INCLUDED

/* -------------------------------------------------------------------- */
/*      To avoid dependence on CPL, just define AVOID_CPL when          */
/*      compiling.                                                      */
/* -------------------------------------------------------------------- */
#ifndef AVOID_CPL
#include "cpl_conv.h"
#include "cpl_string.h"
#else

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#define CPL_C_START
#define CPL_C_END

#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif

#ifndef EQUAL
#if defined(_WIN32)
#define EQUALN(a, b, n) (strnicmp(a, b, n) == 0)
#define EQUAL(a, b) (stricmp(a, b) == 0)
#else
#define EQUALN(a, b, n) (strncasecmp(a, b, n) == 0)
#define EQUAL(a, b) (strcasecmp(a, b) == 0)
#endif
#endif

#ifndef ABS
#define ABS(x) (((x) >= 0) ? (x) : -(x))
#endif

#ifndef MIN
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#endif

#define VSIFTellL ftell
#define VSIFOpenL fopen
#define VSIFCloseL fclose
#define VSIFReadL fread
#define VSIFWriteL fwrite
#define CPLMalloc malloc
#define CPLCalloc calloc
#define CPLFree free
#define GInt16 short
#define GByte unsigned char
#define VSIFSeekL fseek
#define CPLAssert assert
#define VSIStrdup strdup

#endif

/* -------------------------------------------------------------------- */
/*      DTED information structure.  All of this can be considered      */
/*      public information.                                             */
/* -------------------------------------------------------------------- */
CPL_C_START

#define DTED_UHL_SIZE 80
#define DTED_DSI_SIZE 648
#define DTED_ACC_SIZE 2700

#define DTED_NODATA_VALUE -32767

typedef struct
{
    VSILFILE *fp;
    int bUpdate;

    int nXSize;
    int nYSize;

    double dfULCornerX; /* in long/lat degrees */
    double dfULCornerY;
    double dfPixelSizeX;
    double dfPixelSizeY;

    int nUHLOffset;
    char *pachUHLRecord;

    int nDSIOffset;
    char *pachDSIRecord;

    int nACCOffset;
    char *pachACCRecord;

    int nDataOffset;

    int bRewriteHeaders;

    int *
        panMapLogicalColsToOffsets; /* size of nXSize elements. Might be NULL */

    bool bAssumeConformant;

} DTEDInfo;

/* -------------------------------------------------------------------- */
/*      DTED access API.  Get info directly from the structure          */
/*      (DTEDInfo).                                                     */
/* -------------------------------------------------------------------- */
DTEDInfo *DTEDOpen(const char *pszFilename, const char *pszAccess,
                   int bTestOpen);
DTEDInfo *DTEDOpenEx(VSILFILE *fp, const char *pszFilename,
                     const char *pszAccess, int bTestOpen);

/**     Read one single sample. The coordinates are given from the
        top-left corner of the file (contrary to the internal
        organization or a DTED file)
*/
int DTEDReadPoint(DTEDInfo *psDInfo, int nXOff, int nYOff, GInt16 *panVal);

/**    Read one profile line.  These are organized in bottom to top
       order starting from the leftmost column (0).
*/
int DTEDReadProfile(DTEDInfo *psDInfo, int nColumnOffset, GInt16 *panData);

/* Extended version of DTEDReadProfile that enables the user to specify */
/* whether the checksums should be verified */
int DTEDReadProfileEx(DTEDInfo *psDInfo, int nColumnOffset, GInt16 *panData,
                      int bVerifyChecksum);

/**    Write one profile line.
       @warning Contrary to DTEDReadProfile,
                the profile should be organized from top to bottom
*/
int DTEDWriteProfile(DTEDInfo *psDInfo, int nColumnOffset, GInt16 *panData);

void DTEDClose(DTEDInfo *);

const char *DTEDCreate(const char *pszFilename, int nLevel, int nLLOriginLat,
                       int nLLOriginLong);

/* -------------------------------------------------------------------- */
/*      Metadata support.                                               */
/* -------------------------------------------------------------------- */
typedef enum
{
    DTEDMD_VERTACCURACY_UHL = 1, /* UHL 29+4, ACC 8+4 */
    DTEDMD_VERTACCURACY_ACC = 2,
    DTEDMD_SECURITYCODE_UHL = 3, /* UHL 33+3, DSI 4+1 */
    DTEDMD_SECURITYCODE_DSI = 4,
    DTEDMD_UNIQUEREF_UHL = 5, /* UHL 36+12, DSI 65+15*/
    DTEDMD_UNIQUEREF_DSI = 6,
    DTEDMD_DATA_EDITION = 7,       /* DSI 88+2 */
    DTEDMD_MATCHMERGE_VERSION = 8, /* DSI 90+1 */
    DTEDMD_MAINT_DATE = 9,         /* DSI 91+4 */
    DTEDMD_MATCHMERGE_DATE = 10,   /* DSI 95+4 */
    DTEDMD_MAINT_DESCRIPTION = 11, /* DSI 99+4 */
    DTEDMD_PRODUCER = 12,          /* DSI 103+8 */
    DTEDMD_VERTDATUM = 13,         /* DSI 142+3 */
    DTEDMD_DIGITIZING_SYS = 14,    /* DSI 150+10 */
    DTEDMD_COMPILATION_DATE = 15,  /* DSI 160+4 */
    DTEDMD_HORIZACCURACY = 16,     /* ACC 4+4 */
    DTEDMD_REL_HORIZACCURACY = 17, /* ACC 12+4 */
    DTEDMD_REL_VERTACCURACY = 18,  /* ACC 16+4 */
    DTEDMD_HORIZDATUM = 19,        /* DSI 145+5 */
    DTEDMD_ORIGINLONG = 20,        /* UHL 5+7 */
    DTEDMD_ORIGINLAT = 21,         /* UHL 13+7 */
    DTEDMD_NIMA_DESIGNATOR = 22,   /* DSI 60 + 5 */
    DTEDMD_PARTIALCELL_DSI = 23,   /* DSI 289 + 2 */
    DTEDMD_SECURITYCONTROL = 24,
    DTEDMD_SECURITYHANDLING = 25,
    DTEDMD_MAX = 25
} DTEDMetaDataCode;

char *DTEDGetMetadata(DTEDInfo *, DTEDMetaDataCode);
int DTEDSetMetadata(DTEDInfo *, DTEDMetaDataCode, const char *);

/* -------------------------------------------------------------------- */
/*      Point stream writer API.                                        */
/* -------------------------------------------------------------------- */
void *DTEDCreatePtStream(const char *pszPath, int nLevel);
int DTEDWritePt(void *hStream, double dfLong, double dfLat, double dfElev);
void DTEDFillPtStream(void *hStream, int nPixelSearchDist);
void DTEDPtStreamSetMetadata(void *hStream, DTEDMetaDataCode, const char *);
void DTEDClosePtStream(void *hStream);
void DTEDPtStreamTrimEdgeOnlyTiles(void *hStream);

CPL_C_END

#endif /* ndef DTED_API_H_INCLUDED */
