#ifndef __PGS_KEY_H__
#define __PGS_KEY_H__

#include "types.h"

/* Declarations of key build functions */

#define KEYSIZE 24				/* the key size for one entry */
#define BPCKSIZE (KEYSIZE/6)	/* the key size for one entry per coordinate */

/*
 * The coordinate value has to be between -MAXCVALUE .. MAXCVALUE
 */
#define MAXCVALUE ( (1 << (8 * BPCKSIZE - 2)) - 1 )


/* Dummy definition to get LEAF_KEY_SIZE always right -- we rather do not dare
 * to mess around with offsetof() inside 'union {};'
 */

typedef struct
{
	char		vl_len_[4];
	union
	{
		struct					/* the compiler will probably insert 4 bytes
								 * of padding here */
		{
			float8		lat,
						lng;
		};
	};
}			GiSTSPointKey_Leaf;

typedef struct
{
	char		vl_len_[4];
	union
	{
		struct					/* the compiler will probably insert 4 bytes
								 * of padding here */
		{
			float8		lat,
						lng;
		};
		struct
		{
			int32		k[6];
		};
	};
} GiSTSPointKey;

#define INTERNAL_KEY_SIZE sizeof(GiSTSPointKey)
#define LEAF_KEY_SIZE sizeof(GiSTSPointKey_Leaf)
#define IS_LEAF(key) (VARSIZE(key) == LEAF_KEY_SIZE)

#define ALLOC_LEAF_KEY(key) do { \
	key = (GiSTSPointKey *)palloc0(LEAF_KEY_SIZE); \
	SET_VARSIZE(key, LEAF_KEY_SIZE); \
} while (0) ;

#define ALLOC_INTERNAL_KEY(key) do { \
	key = (GiSTSPointKey *)palloc0(INTERNAL_KEY_SIZE); \
	SET_VARSIZE(key, INTERNAL_KEY_SIZE); \
} while (0) ;

/*
 * Returns the union of two keys. Result is placed into 'kunion'.
 */
extern void spherekey_union_two(int32 *kunion, const int32 *key);

/*
 * Returns the intersection of two keys. Returns NULL if there is
 * no intersection. Result is placed into 'kinter'.
 */
extern bool spherekey_inter_two(int32 *kinter, const int32 *key);

/*
 * Generates the key of a spherical point and returns it. Result is placed
 * into 'k'.
 */
extern void spherepoint_gen_key(int32 *k, const SPoint *sp);

/*
 * Generates the circle's key and returns it. Result is placed into 'k'.
 */
extern void spherecircle_gen_key(int32 *k, const SCIRCLE *c);

/*
 * Generates the key of a spherical ellipse and returns it. Result is placed
 * into 'k'.
 */
extern void sphereellipse_gen_key(int32 *k, const SELLIPSE *e);

/*
 * Generates the key of a spherical line and returns it. Result is placed
 * into 'k'.
 */
extern void sphereline_gen_key(int32 *k, const SLine *sl);

/*
 * Generates the key of a polygon and returns it. Result is placed into 'k'.
 */
extern void spherepoly_gen_key(int32 *k, const SPOLY *sp);

/*
 * Generates the key of a path and returns it. Result is placed into 'k'.
 */
extern void spherepath_gen_key(int32 *k, const SPATH *sp);

/*
 * Generates the key of a box and returns it. Result is placed into 'k'.
 */
extern void spherebox_gen_key(int32 *key, const SBOX *box);

/*
 * Returns true if the first key is less than the second key.
 */
extern Datum spherekey_lt(PG_FUNCTION_ARGS);

/*
 * Returns true if the first key is less or equal than the second key.
 */
extern Datum spherekey_le(PG_FUNCTION_ARGS);

/*
 * Returns true if two keys are equal.
 */
extern Datum spherekey_eq(PG_FUNCTION_ARGS);

/*
 * Returns true if two keys are not equal.
 */
extern Datum spherekey_eq_neg(PG_FUNCTION_ARGS);

/*
 * Returns true if the first key is greater or equal than the second key.
 */
extern Datum spherekey_ge(PG_FUNCTION_ARGS);

/*
 * Returns true if the first key is greater than the second key.
 */
extern Datum spherekey_gt(PG_FUNCTION_ARGS);

/*
 * Returns relationship between the two keys.
 * Calls skey_cmp(const int32 *, const int32 *) for two keys.
 */
extern Datum spherekey_cmp(PG_FUNCTION_ARGS);

/*
 * Returns relationship between the keys of two spherical points.
 * Calls skey_cmp(const int32 *, const int32 *) for two points.
 */
extern Datum spherepoint_cmp(PG_FUNCTION_ARGS);

/*
 * Returns relationship between the keys of two spherical circles.
 * Calls skey_cmp(const int32 *, const int32 *) for two circles.
 */
extern Datum spherecircle_cmp(PG_FUNCTION_ARGS);

/*
 * Returns relationship between the keys of two spherical ellipses.
 * Calls skey_cmp(const int32 *, const int32 *) for two ellipses.
 */
extern Datum sphereellipse_cmp(PG_FUNCTION_ARGS);

/*
 * Returns relationship between the keys of two spherical lines.
 * Calls skey_cmp(const int32 *, const int32 *) for two lines.
 */
extern Datum sphereline_cmp(PG_FUNCTION_ARGS);

/*
 * Returns relationship between the keys of two spherical paths.
 * Calls skey_cmp(const int32 *, const int32 *) for two paths.
 */
extern Datum spherepath_cmp(PG_FUNCTION_ARGS);

/*
 * Returns relationship between the keys of two spherical polygons.
 * Calls skey_cmp(const int32 *, const int32 *) for two polygons.
 */
extern Datum spherepoly_cmp(PG_FUNCTION_ARGS);

/*
 * Returns relationship between the keys of two spherical boxes.
 * Calls skey_cmp(const int32 *, const int32 *) for two boxes.
 */
extern Datum spherebox_cmp(PG_FUNCTION_ARGS);

#endif
