/******************************************************************************
 * $Id$
 *
 * Project:  MapServer
 * Purpose:  Shapefile access API
 * Author:   Steve Lime and the MapServer team.
 *
 ******************************************************************************
 * Copyright (c) 1996-2005 Regents of the University of Minnesota.
 *
 * 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 of this Software or works derived from this 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 MAPSHAPE_H
#define MAPSHAPE_H

#include <stdio.h>
#include "mapprimitive.h"
#include "mapproject.h"

#include "cpl_vsi.h"

#ifdef __cplusplus
extern "C" {
#endif

#define SHX_BUFFER_PAGE 1024

#ifndef SWIG
#define MS_PATH_LENGTH 1024

/* Shapefile types */
#define SHP_POINT 1
#define SHP_ARC 3
#define SHP_POLYGON 5
#define SHP_MULTIPOINT 8

#define SHP_POINTZ 11
#define SHP_ARCZ 13
#define SHP_POLYGONZ 15
#define SHP_MULTIPOINTZ 18

#define SHP_POINTM 21
#define SHP_ARCM 23
#define SHP_POLYGONM 25
#define SHP_MULTIPOINTM 28
#endif

#define MS_SHAPEFILE_POINT 1
#define MS_SHAPEFILE_ARC 3
#define MS_SHAPEFILE_POLYGON 5
#define MS_SHAPEFILE_MULTIPOINT 8

#define MS_SHP_POINTZ 11
#define MS_SHP_ARCZ 13
#define MS_SHP_POLYGONZ 15
#define MS_SHP_MULTIPOINTZ 18

#define MS_SHP_POINTM 21
#define MS_SHP_ARCM 23
#define MS_SHP_POLYGONM 25
#define MS_SHP_MULTIPOINTM 28

#ifndef SWIG
typedef unsigned char uchar;

typedef struct {
  VSILFILE *fpSHP;
  VSILFILE *fpSHX;

  int nShapeType; /* SHPT_* */
  int nFileSize;  /* SHP file */

  int nRecords;
  int nMaxRecords;

  int *panRecOffset;
  int *panRecSize;
  ms_bitarray panRecLoaded;
  int panRecAllLoaded;

  double adBoundsMin[4];
  double adBoundsMax[4];

  int bUpdated;

  int nBufSize; /* these used static vars in shape readers, moved to be
                   thread-safe */
  uchar *pabyRec;
  int nPartMax;
  int *panParts;

} SHPInfo;
typedef SHPInfo *SHPHandle;
#endif

/************************************************************************/
/*                          DBFInfo                                     */
/************************************************************************/

/**
 * An object containing information about a DBF file
 *
 */
typedef struct {
#ifdef SWIG
    %immutable;
#endif

  int nRecords; ///< Number of records in the DBF
  int nFields;  ///< Number of fields in the DBF

#ifndef SWIG
  VSILFILE *fp;
  unsigned int nRecordLength;
  int nHeaderLength;

  int *panFieldOffset;
  int *panFieldSize;
  int *panFieldDecimals;
  char *pachFieldType;

  char *pszHeader;

  int nCurrentRecord;
  int bCurrentRecordModified;
  char *pszCurrentRecord;

  int bNoHeader;
  int bUpdated;

  char *pszStringField;
  int nStringFieldLen;

  char *pszEncoding;
#endif /* not SWIG */
} DBFInfo;

typedef DBFInfo *DBFHandle;

typedef enum { FTString, FTInteger, FTDouble, FTInvalid } DBFFieldType;

/************************************************************************/
/*                          shapefileObj                                */
/************************************************************************/

/**
 * An object representing a Shapefile. There is no write access to this object
 * using MapScript.
 */
typedef struct {
#ifdef SWIG
    %immutable;
#endif

  int type;       ///< Shapefile type - see mapshape.h for values of type
  int numshapes;  ///< Number of shapes
  rectObj bounds; ///< Extent of shapes

#ifndef SWIG
  char source[MS_PATH_LENGTH]; /* full path to this file data */
  int lastshape;
  ms_bitarray status;
  int isopen;
  SHPHandle hSHP; /* SHP/SHX file pointer */
  DBFHandle hDBF; /* DBF file pointer */
#endif

} shapefileObj;

#ifndef SWIG
/* layerInfo structure for tiled shapefiles */
typedef struct {
  shapefileObj *shpfile;
  shapefileObj *tileshpfile;
  int tilelayerindex;
  projectionObj sTileProj;
  rectObj searchrect;
  reprojectionObj *reprojectorFromTileProjToLayerProj;
} msTiledSHPLayerInfo;

/* shapefileObj function prototypes  */
MS_DLL_EXPORT int msShapefileOpenHandle(shapefileObj *shpfile,
                                        const char *filename, SHPHandle hSHP,
                                        DBFHandle hDBF);
MS_DLL_EXPORT int msShapefileOpenVirtualFile(shapefileObj *shpfile,
                                             const char *filename,
                                             VSILFILE *fpSHP, VSILFILE *fpSHX,
                                             VSILFILE *fpDBF, int log_failures);
MS_DLL_EXPORT int msShapefileOpen(shapefileObj *shpfile, const char *mode,
                                  const char *filename, int log_failures);
MS_DLL_EXPORT int msShapefileCreate(shapefileObj *shpfile, char *filename,
                                    int type);
MS_DLL_EXPORT void msShapefileClose(shapefileObj *shpfile);
MS_DLL_EXPORT int msShapefileWhichShapes(shapefileObj *shpfile, rectObj rect,
                                         int debug);

/* SHP/SHX function prototypes */
MS_DLL_EXPORT SHPHandle msSHPOpenVirtualFile(VSILFILE *fpSHP, VSILFILE *fpSHX);
MS_DLL_EXPORT SHPHandle msSHPOpen(const char *pszShapeFile,
                                  const char *pszAccess);
MS_DLL_EXPORT SHPHandle msSHPCreate(const char *pszShapeFile, int nShapeType);
MS_DLL_EXPORT void msSHPClose(SHPHandle hSHP);
MS_DLL_EXPORT void msSHPGetInfo(SHPHandle hSHP, int *pnEntities,
                                int *pnShapeType);
MS_DLL_EXPORT int msSHPReadBounds(SHPHandle psSHP, int hEntity,
                                  rectObj *padBounds);
MS_DLL_EXPORT void msSHPReadShape(SHPHandle psSHP, int hEntity,
                                  shapeObj *shape);
MS_DLL_EXPORT int msSHPReadPoint(SHPHandle psSHP, int hEntity, pointObj *point);
MS_DLL_EXPORT int msSHPWriteShape(SHPHandle psSHP, shapeObj *shape);
MS_DLL_EXPORT int msSHPWritePoint(SHPHandle psSHP, pointObj *point);

/* tiledShapefileObj function prototypes are in mapserver.h */

/* XBase function prototypes */
MS_DLL_EXPORT DBFHandle msDBFOpenVirtualFile(VSILFILE *fp);
MS_DLL_EXPORT DBFHandle msDBFOpen(const char *pszDBFFile,
                                  const char *pszAccess);
MS_DLL_EXPORT void msDBFClose(DBFHandle hDBF);
MS_DLL_EXPORT DBFHandle msDBFCreate(const char *pszDBFFile);

MS_DLL_EXPORT int msDBFGetFieldCount(DBFHandle psDBF);
MS_DLL_EXPORT int msDBFGetRecordCount(DBFHandle psDBF);
MS_DLL_EXPORT int msDBFAddField(DBFHandle hDBF, const char *pszFieldName,
                                DBFFieldType eType, int nWidth, int nDecimals);

MS_DLL_EXPORT DBFFieldType msDBFGetFieldInfo(DBFHandle psDBF, int iField,
                                             char *pszFieldName, int *pnWidth,
                                             int *pnDecimals);

MS_DLL_EXPORT int msDBFReadIntegerAttribute(DBFHandle hDBF, int iShape,
                                            int iField);
MS_DLL_EXPORT double msDBFReadDoubleAttribute(DBFHandle hDBF, int iShape,
                                              int iField);
MS_DLL_EXPORT const char *msDBFReadStringAttribute(DBFHandle hDBF, int iShape,
                                                   int iField);

MS_DLL_EXPORT int msDBFWriteIntegerAttribute(DBFHandle hDBF, int iShape,
                                             int iField, int nFieldValue);
MS_DLL_EXPORT int msDBFWriteDoubleAttribute(DBFHandle hDBF, int iShape,
                                            int iField, double dFieldValue);
MS_DLL_EXPORT int msDBFWriteStringAttribute(DBFHandle hDBF, int iShape,
                                            int iField,
                                            const char *pszFieldValue);

MS_DLL_EXPORT char **msDBFGetItems(DBFHandle dbffile);
MS_DLL_EXPORT char **msDBFGetValues(DBFHandle dbffile, int record);
MS_DLL_EXPORT char **msDBFGetValueList(DBFHandle dbffile, int record,
                                       int *itemindexes, int numitems);
MS_DLL_EXPORT int *msDBFGetItemIndexes(DBFHandle dbffile, char **items,
                                       int numitems);
MS_DLL_EXPORT int msDBFGetItemIndex(DBFHandle dbffile, char *name);

#endif

#ifdef __cplusplus
}
#endif

#endif /* MAPSHAPE_H */
