#ifndef _XPLMMap_h_
#define _XPLMMap_h_

/*
 * Copyright 2005-2012 Sandy Barbour and Ben Supnik All rights reserved.  See
 * license.txt for usage. X-Plane SDK Version: 2.1.1                          
 *
 */

/***************************************************************************
 * XPLMMap
 ***************************************************************************/
/*
 * This API allows you to create new layers within X-Plane maps. Your layers
 * can draw arbitrary OpenGL, but they conveniently also have access to
 * X-Plane's built-in icon and label drawing functions.
 * 
 * As of X-Plane 11, map drawing happens in three stages:
 * 
 * 1. backgrounds and "fill,"
 * 2. icons, and
 * 3. labels.
 * 
 * Thus, all background drawing gets layered beneath all icons, which likewise
 * get layered beneath all labels. Within each stage, the map obeys a
 * consistent layer ordering, such that "fill" layers (layers that cover a
 * large amount of map area, like the terrain and clouds) appear beneath
 * "markings" layers (like airport icons). This ensures that layers with fine
 * details don't get obscured by layers with larger details.
 * 
 * The XPLM map API reflects both aspects of this draw layering: you can
 * register a layer as providing either markings or fill, and X-Plane will
 * draw your fill layers beneath your markings layers (regardless of
 * registration order). Likewise, you are guaranteed that your layer's icons
 * (added from within an icon callback) will go above your layer's OpenGL
 * drawing, and your labels will go above your icons.
 * 
 * The XPLM guarantees that all plugin-created fill layers go on top of all
 * native X-Plane fill layers, and all plugin-created markings layers go on
 * top of all X-Plane markings layers (with the exception of the aircraft
 * icons). It also guarantees that the draw order of your own plugin's layers
 * will be consistent. But, for layers created by different plugins, the only
 * guarantee is that we will draw all of one plugin's layers of each type
 * (fill, then markings), then all of the others'; we don't guarantee which
 * plugin's fill and markings layers go on top of the other's.
 * 
 * As of X-Plane 11, maps use true cartographic projections for their drawing,
 * and different maps may use different projections. For that reason, all
 * drawing calls include an opaque handle for the projection you should use to
 * do the drawing. Any time you would draw at a particular latitude/longitude,
 * you'll need to ask the projection to translate that position into "map
 * coordinates." (Note that the projection is guaranteed not to change between
 * calls to your prepare-cache hook, so if you cache your map coordinates
 * ahead of time, there's no need to re-project them when you actually draw.)
 * 
 * In addition to mapping normal latitude/longitude locations into map
 * coordinates, the projection APIs also let you know the current heading for
 * north. (Since X-Plane 11 maps can rotate to match the heading of the user's
 * aircraft, it's not safe to assume that north is at zero degrees rotation.) 
 *
 */

#include "XPLMDefs.h"

#ifdef __cplusplus
extern "C" {
#endif

#if defined(XPLM300)
/***************************************************************************
 * DRAWING CALLBACKS
 ***************************************************************************/
/*
 * When you create a new map layer (using XPLMCreateMapLayer), you can provide
 * any or all of these callbacks. They allow you to insert your own OpenGL
 * drawing, text labels, and icons into the X-Plane map at the appropriate
 * places, allowing your layer to behave as similarly to X-Plane's built-in
 * layers as possible.                                                        
 *
 */


/*
 * XPLMMapLayerID
 * 
 * This is an opaque handle for a plugin-created map layer. Pass it to the map
 * drawing APIs from an appropriate callback to draw in the layer you created.
 *
 */
typedef void * XPLMMapLayerID;

/*
 * XPLMMapProjectionID
 * 
 * This is an opaque handle for a map projection. Pass it to the projection
 * APIs to translate between map coordinates and latitude/longitudes.         
 *
 */
typedef void * XPLMMapProjectionID;

/*
 * XPLMMapStyle
 * 
 * Indicates the visual style being drawn by the map. In X-Plane, the user can
 * choose between a number of map types, and different map types may have use
 * a different visual representation for the same elements (for instance, the
 * visual style of the terrain layer changes drastically between the VFR and
 * IFR layers), or certain layers may be disabled entirely in some map types
 * (e.g., localizers are only visible in the IFR low-enroute style).          
 *
 */
enum {
    xplm_MapStyle_VFR_Sectional              = 0,

    xplm_MapStyle_IFR_LowEnroute             = 1,

    xplm_MapStyle_IFR_HighEnroute            = 2,


};
typedef int XPLMMapStyle;

/*
 * XPLMMapDrawingCallback_f
 * 
 * This is the OpenGL map drawing callback for plugin-created map layers. You
 * can perform arbitrary OpenGL drawing from this callback, with one
 * exception: changes to the Z-buffer are not permitted, and will result in
 * map drawing errors.
 * 
 * All drawing done from within this callback appears beneath all built-in
 * X-Plane icons and labels, but above the built-in "fill" layers (layers
 * providing major details, like terrain and water). Note, however, that the
 * relative ordering between the drawing callbacks of different plugins is not
 * guaranteed.                                                                
 *
 */
typedef void (* XPLMMapDrawingCallback_f)(
                         XPLMMapLayerID       inLayer,    
                         const float *        inMapBoundsLeftTopRightBottom,    
                         float                zoomRatio,    
                         float                mapUnitsPerUserInterfaceUnit,    
                         XPLMMapStyle         mapStyle,    
                         XPLMMapProjectionID  projection,    
                         void *               inRefcon);    

/*
 * XPLMMapIconDrawingCallback_f
 * 
 * This is the icon drawing callback that enables plugin-created map layers to
 * draw icons using X-Plane's built-in icon drawing functionality. You can
 * request an arbitrary number of PNG icons to be drawn via
 * XPLMDrawMapIconFromSheet() from within this callback, but you may not
 * perform any OpenGL drawing here.
 * 
 * Icons enqueued by this function will appear above all OpenGL drawing
 * (performed by your optional XPLMMapDrawingCallback_f), and above all
 * built-in X-Plane map icons of the same layer type ("fill" or "markings," as
 * determined by the XPLMMapLayerType in your XPLMCreateMapLayer_t). Note,
 * however, that the relative ordering between the drawing callbacks of
 * different plugins is not guaranteed.                                       
 *
 */
typedef void (* XPLMMapIconDrawingCallback_f)(
                         XPLMMapLayerID       inLayer,    
                         const float *        inMapBoundsLeftTopRightBottom,    
                         float                zoomRatio,    
                         float                mapUnitsPerUserInterfaceUnit,    
                         XPLMMapStyle         mapStyle,    
                         XPLMMapProjectionID  projection,    
                         void *               inRefcon);    

/*
 * XPLMMapLabelDrawingCallback_f
 * 
 * This is the label drawing callback that enables plugin-created map layers
 * to draw text labels using X-Plane's built-in labeling functionality. You
 * can request an arbitrary number of text labels to be drawn via
 * XPLMDrawMapLabel() from within this callback, but you may not perform any
 * OpenGL drawing here.
 * 
 * Labels enqueued by this function will appear above all OpenGL drawing
 * (performed by your optional XPLMMapDrawingCallback_f), and above all
 * built-in map icons and labels of the same layer type ("fill" or "markings,"
 * as determined by the XPLMMapLayerType in your XPLMCreateMapLayer_t). Note,
 * however, that the relative ordering between the drawing callbacks of
 * different plugins is not guaranteed.                                       
 *
 */
typedef void (* XPLMMapLabelDrawingCallback_f)(
                         XPLMMapLayerID       inLayer,    
                         const float *        inMapBoundsLeftTopRightBottom,    
                         float                zoomRatio,    
                         float                mapUnitsPerUserInterfaceUnit,    
                         XPLMMapStyle         mapStyle,    
                         XPLMMapProjectionID  projection,    
                         void *               inRefcon);    

#endif /* XPLM300 */
#if defined(XPLM300)
/***************************************************************************
 * LAYER MANAGEMENT CALLBACKS
 ***************************************************************************/
/*
 * These are various "bookkeeping" callbacks that your map layer can receive
 * (if you provide the callback in your XPLMCreateMapLayer_t). They allow you
 * to manage the lifecycle of your layer, as well as cache any
 * computationally-intensive preparation you might need for drawing.          
 *
 */


/*
 * XPLMMapPrepareCacheCallback_f
 * 
 * A callback used to allow you to cache whatever information your layer needs
 * to draw in the current map area.
 * 
 * This is called each time the map's total bounds change. This is typically
 * triggered by new DSFs being loaded, such that X-Plane discards old,
 * now-distant DSFs and pulls in new ones. At that point, the available bounds
 * of the map also change to match the new DSF area.
 * 
 * By caching just the information you need to draw in this area, your future
 * draw calls can be made faster, since you'll be able to simply "splat" your
 * precomputed information each frame.
 * 
 * We guarantee that the map projection will not change between successive
 * prepare cache calls, nor will any draw call give you bounds outside these
 * total map bounds. So, if you cache the projected map coordinates of all the
 * items you might want to draw in the total map area, you can be guaranteed
 * that no draw call will be asked to do any new work.                        
 *
 */
typedef void (* XPLMMapPrepareCacheCallback_f)(
                         XPLMMapLayerID       inLayer,    
                         const float *        inTotalMapBoundsLeftTopRightBottom,    
                         XPLMMapProjectionID  projection,    
                         void *               inRefcon);    

/*
 * XPLMMapWillBeDeletedCallback_f
 * 
 * Called just before your map layer gets deleted. Because SDK-created map
 * layers have the same lifetime as the X-Plane map that contains them, if the
 * map gets unloaded from memory, your layer will too.                        
 *
 */
typedef void (* XPLMMapWillBeDeletedCallback_f)(
                         XPLMMapLayerID       inLayer,    
                         void *               inRefcon);    

#endif /* XPLM300 */
#if defined(XPLM300)
/***************************************************************************
 * MAP LAYER CREATION AND DESTRUCTION
 ***************************************************************************/
/*
 * Enables the creation of new map layers. Layers are created for a particular
 * instance of the X-Plane map. For instance, if you want your layer to appear
 * in both the normal map interface and the Instructor Operator Station (IOS),
 * you would need two separate calls to XPLMCreateMapLayer(), with two
 * different values for your XPLMCreateMapLayer_t::layer_name.
 * 
 * Your layer's lifetime will be determined by the lifetime of the map it is
 * created in. If the map is destroyed (on the X-Plane side), your layer will
 * be too, and you'll receive a callback to your
 * XPLMMapWillBeDeletedCallback_f.                                            
 *
 */


/*
 * XPLMMapLayerType
 * 
 * Indicates the type of map layer you are creating. Fill layers will always
 * be drawn beneath markings layers.                                          
 *
 */
enum {
     /* A layer that draws "fill" graphics, like weather patterns, terrain, etc.   *
      * Fill layers frequently cover a large portion of the visible map area.      */
    xplm_MapLayer_Fill                       = 0,

     /* A layer that provides markings for particular map features, like NAVAIDs,  *
      * airports, etc. Even dense markings layers cover a small portion of the     *
      * total map area.                                                            */
    xplm_MapLayer_Markings                   = 1,


};
typedef int XPLMMapLayerType;

/* Globally unique identifier for X-Plane's Map window, used as the           *
 * mapToCreateLayerIn parameter in XPLMCreateMapLayer_t                       */
#define XPLM_MAP_USER_INTERFACE "XPLM_MAP_USER_INTERFACE"

/* Globally unique identifier for X-Plane's Instructor Operator Station       *
 * window, used as the mapToCreateLayerIn parameter in XPLMCreateMapLayer_t   */
#define XPLM_MAP_IOS         "XPLM_MAP_IOS"

/*
 * XPLMCreateMapLayer_t
 * 
 * This structure defines all of the parameters used to create a map layer
 * using XPLMCreateMapLayer. The structure will be expanded in future SDK APIs
 * to include more features.  Always set the structSize member to the size of
 * your struct in bytes!
 * 
 * Each layer must be associated with exactly one map instance in X-Plane.
 * That map, and that map alone, will call your callbacks. Likewise, when that
 * map is deleted, your layer will be as well.                                
 *
 */
typedef struct {
     /* Used to inform XPLMCreateMapLayer() of the SDK version you compiled        *
      * against; should always be set to sizeof(XPLMCreateMapLayer_t)              */
     int                       structSize;
     /* Globally unique string identifying the map you want this layer to appear   *
      * in. As of XPLM300, this is limited to one of XPLM_MAP_USER_INTERFACE or    *
      * XPLM_MAP_IOS                                                               */
     const char *              mapToCreateLayerIn;
     /* The type of layer you are creating, used to determine draw order (all      *
      * plugin-created markings layers are drawn above all plugin-created fill     *
      * layers)                                                                    */
     XPLMMapLayerType          layerType;
     /* Optional callback to inform you this layer is being deleted (due to its    *
      * owning map being destroyed)                                                */
     XPLMMapWillBeDeletedCallback_f willBeDeletedCallback;
     /* Optional callback you want to use to prepare your draw cache when the map  *
      * bounds change (set to NULL if you don't want this callback)                */
     XPLMMapPrepareCacheCallback_f prepCacheCallback;
     /* Optional callback you want to use for arbitrary OpenGL drawing, which goes *
      * beneath all icons in the map's layering system (set to NULL if you don't   *
      * want this callback)                                                        */
     XPLMMapDrawingCallback_f  drawCallback;
     /* Optional callback you want to use for drawing icons, which go above all    *
      * built-in X-Plane icons (except the aircraft) in the map's layering system  *
      * (set to NULL if you don't want this callback)                              */
     XPLMMapIconDrawingCallback_f iconCallback;
     /* Optional callback you want to use for drawing map labels, which go above   *
      * all built-in X-Plane icons and labels (except those of aircraft) in the    *
      * map's layering system (set to NULL if you don't want this callback)        */
     XPLMMapLabelDrawingCallback_f labelCallback;
     /* True if you want a checkbox to be created in the map UI to toggle this     *
      * layer on and off; false if the layer should simply always be enabled       */
     int                       showUiToggle;
     /* Short label to use for this layer in the user interface                    */
     const char *              layerName;
     /* A reference to arbitrary data that will be passed to your callbacks        */
     void *                    refcon;
} XPLMCreateMapLayer_t;

/*
 * XPLMCreateMapLayer
 * 
 * This routine creates a new map layer. You pass in an XPLMCreateMapLayer_t
 * structure with all of the fields set in.  You must set the structSize of
 * the structure to the size of the actual structure you used.
 * 
 * Returns NULL if the layer creation failed. This happens most frequently
 * because the map you specified in your
 * XPLMCreateMapLayer_t::mapToCreateLayerIn field doesn't exist (that is, if
 * XPLMMapExists() returns 0 for the specified map). You can use
 * XPLMRegisterMapCreationHook() to get a notification each time a new map is
 * opened in X-Plane, at which time you can create layers in it.              
 *
 */
XPLM_API XPLMMapLayerID XPLMCreateMapLayer(
                         XPLMCreateMapLayer_t * inParams);    

/*
 * XPLMDestroyMapLayer
 * 
 * Destroys a map layer you created (calling your
 * XPLMMapWillBeDeletedCallback_f if applicable). Returns true if a deletion
 * took place.                                                                
 *
 */
XPLM_API int        XPLMDestroyMapLayer(
                         XPLMMapLayerID       inLayer);    

/*
 * XPLMMapCreatedCallback_f
 * 
 * A callback to notify your plugin that a new map has been created in
 * X-Plane. This is the best time to add a custom map layer using
 * XPLMCreateMapLayer().
 * 
 * No OpenGL drawing is permitted within this callback.                       
 *
 */
typedef void (* XPLMMapCreatedCallback_f)(
                         const char *         mapIdentifier,    
                         void *               refcon);    

/*
 * XPLMRegisterMapCreationHook
 * 
 * Registers your callback to receive a notification each time a new map is
 * constructed in X-Plane. This callback is the best time to add your custom
 * map layer using XPLMCreateMapLayer().
 * 
 * Note that you will not be notified about any maps that already exist---you
 * can use XPLMMapExists() to check for maps that were created previously.    
 *
 */
XPLM_API void       XPLMRegisterMapCreationHook(
                         XPLMMapCreatedCallback_f callback,    
                         void *               refcon);    

/*
 * XPLMMapExists
 * 
 * Returns 1 if the map with the specified identifier already exists in
 * X-Plane. In that case, you can safely call XPLMCreateMapLayer() specifying
 * that your layer should be added to that map.                               
 *
 */
XPLM_API int        XPLMMapExists(
                         const char *         mapIdentifier);    

#endif /* XPLM300 */
#if defined(XPLM300)
/***************************************************************************
 * MAP DRAWING
 ***************************************************************************/
/*
 * These APIs are only valid from within a map drawing callback (one of
 * XPLMIconDrawingCallback_t or XPLMMapLabelDrawingCallback_f). Your drawing
 * callbacks are registered when you create a new map layer as part of your
 * XPLMCreateMapLayer_t. The functions here hook into X-Plane's built-in map
 * drawing functionality for icons and labels, so that you get a consistent
 * style with the rest of the X-Plane map.
 * 
 * Note that the X-Plane 11 map introduces a strict ordering: layers of type
 * xplm_MapLayer_Fill get drawn beneath all xplm_MapLayer_Markings layers.
 * Likewise, all OpenGL drawing (performed in your layer's
 * XPLMMapDrawingCallback_f) will appear beneath any icons and labels you
 * draw.                                                                      
 *
 */


/*
 * XPLMMapOrientation
 * 
 * Indicates whether a map element should be match its rotation to the map
 * itself, or to the user interface. For instance, the map itself may be
 * rotated such that "up" matches the user's aircraft, but you may want to
 * draw a text label such that it is always rotated zero degrees relative to
 * the user's perspective. In that case, you would have it draw with UI
 * orientation.                                                               
 *
 */
enum {
     /* Orient such that a 0 degree rotation matches the map's north               */
    xplm_MapOrientation_Map                  = 0,

     /* Orient such that a 0 degree rotation is "up" relative to the user interface*/
    xplm_MapOrientation_UI                   = 1,


};
typedef int XPLMMapOrientation;

/*
 * XPLMDrawMapIconFromSheet
 * 
 * Enables plugin-created map layers to draw PNG icons using X-Plane's
 * built-in icon drawing functionality. Only valid from within an
 * XPLMIconDrawingCallback_t (but you can request an arbitrary number of icons
 * to be drawn from within your callback).
 * 
 * X-Plane will automatically manage the memory for your texture so that it
 * only has to be loaded from disk once as long as you continue drawing it
 * per-frame. (When you stop drawing it, the memory may purged in a "garbage
 * collection" pass, require a load from disk in the future.)
 * 
 * Instead of having X-Plane draw a full PNG, this method allows you to use UV
 * coordinates to request a portion of the image to be drawn. This allows you
 * to use a single texture load (of an icon sheet, for example) to draw many
 * icons. Doing so is much more efficient than drawing a dozen different small
 * PNGs.
 * 
 * The UV coordinates used here treat the texture you load as being comprised
 * of a number of identically sized "cells." You specify the width and height
 * in cells (ds and dt, respectively), as well as the coordinates within the
 * cell grid for the sub-image you'd like to draw.
 * 
 * Note that you can use different ds and dt values in subsequent calls with
 * the same texture sheet. This enables you to use icons of different sizes in
 * the same sheet if you arrange them properly in the PNG.
 * 
 * This function is only valid from within an XPLMIconDrawingCallback_t (but
 * you can request an arbitrary number of icons to be drawn from within your
 * callback).                                                                 
 *
 */
XPLM_API void       XPLMDrawMapIconFromSheet(
                         XPLMMapLayerID       layer,    
                         const char *         inPngPath,    
                         int                  s,    
                         int                  t,    
                         int                  ds,    
                         int                  dt,    
                         float                mapX,    
                         float                mapY,    
                         XPLMMapOrientation   orientation,    
                         float                rotationDegrees,    
                         float                mapWidth);    

/*
 * XPLMDrawMapLabel
 * 
 * Enables plugin-created map layers to draw text labels using X-Plane's
 * built-in labeling functionality. Only valid from within an
 * XPLMMapLabelDrawingCallback_f (but you can request an arbitrary number of
 * text labels to be drawn from within your callback).                        
 *
 */
XPLM_API void       XPLMDrawMapLabel(
                         XPLMMapLayerID       layer,    
                         const char *         inText,    
                         float                mapX,    
                         float                mapY,    
                         XPLMMapOrientation   orientation,    
                         float                rotationDegrees);    

#endif /* XPLM300 */
#if defined(XPLM300)
/***************************************************************************
 * MAP PROJECTIONS
 ***************************************************************************/
/*
 * As of X-Plane 11, the map draws using true cartographic projections, and
 * different maps may use different projections. Thus, to draw at a particular
 * latitude and longitude, you must first transform your real-world
 * coordinates into map coordinates.
 * 
 * The map projection is also responsible for giving you the current scale of
 * the map. That is, the projection can tell you how many map units correspond
 * to 1 meter at a given point.
 * 
 * Finally, the map projection can give you the current rotation of the map.
 * Since X-Plane 11 maps can rotate to match the heading of the aircraft, the
 * map's rotation can potentially change every frame.                         
 *
 */


/*
 * XPLMMapProject
 * 
 * Projects a latitude/longitude into map coordinates. This is the inverse of
 * XPLMMapUnproject().
 * 
 * Only valid from within a map layer callback (one of
 * XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f,
 * XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.)           
 *
 */
XPLM_API void       XPLMMapProject(
                         XPLMMapProjectionID  projection,    
                         double               latitude,    
                         double               longitude,    
                         float *              outX,    
                         float *              outY);    

/*
 * XPLMMapUnproject
 * 
 * Transforms map coordinates back into a latitude and longitude. This is the
 * inverse of XPLMMapProject().
 * 
 * Only valid from within a map layer callback (one of
 * XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f,
 * XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.)           
 *
 */
XPLM_API void       XPLMMapUnproject(
                         XPLMMapProjectionID  projection,    
                         float                mapX,    
                         float                mapY,    
                         double *             outLatitude,    
                         double *             outLongitude);    

/*
 * XPLMMapScaleMeter
 * 
 * Returns the number of map units that correspond to a distance of one meter
 * at a given set of map coordinates.
 * 
 * Only valid from within a map layer callback (one of
 * XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f,
 * XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.)           
 *
 */
XPLM_API float      XPLMMapScaleMeter(
                         XPLMMapProjectionID  projection,    
                         float                mapX,    
                         float                mapY);    

/*
 * XPLMMapGetNorthHeading
 * 
 * Returns the heading (in degrees clockwise) from the positive Y axis in the
 * cartesian mapping coordinate system to true north at the point passed in. 
 * You can use it as a clockwise rotational offset to align icons and other
 * 2-d drawing with true north on the map, compensating for rotations in the
 * map due to projection.
 * 
 * Only valid from within a map layer callback (one of
 * XPLMMapPrepareCacheCallback_f, XPLMMapDrawingCallback_f,
 * XPLMMapIconDrawingCallback_f, or XPLMMapLabelDrawingCallback_f.)           
 *
 */
XPLM_API float      XPLMMapGetNorthHeading(
                         XPLMMapProjectionID  projection,    
                         float                mapX,    
                         float                mapY);    

#endif /* XPLM300 */
#ifdef __cplusplus
}
#endif

#endif
