#pragma once

#ifndef __GISMANAGER_H__
#define __GISMANAGER_H__

#include "map.h"
#include <iostream>
#include <vector>

#include "shapedrawingoptions.h"
#include "labelcategory.h"
#include "shapefilecategory.h"
#include "shapefilecategories.h"
#include "table.h"
#include "shape.h"

//自定义像素点
#pragma pack(1)
struct PtPixel
{

	PtPixel()
	{
		_ptX = 0;
		_ptY = 0;
	}

	PtPixel(int x, int y)
	{
		_ptX = x;
		_ptY = y;
	}

	int _ptX;
	int _ptY;
};

//自定义双精度坐标点
struct PointXY
{
	PointXY()
	{
		x=0;
		y=0;
	}

	PointXY(double px, double py)
	{
		x = px;
		y = py;
	}

	double x;
	double y;
};

//自定义地理坐标点
struct GeoCoord
{
	GeoCoord()
	{
		lon = lat = alt = 0.0;
	}

	GeoCoord(double x, double y, double z)
	{
		lon = x;
		lat = y;
		alt = z;
	}

	double lon;
	double lat;
	double alt;
};
#pragma pack()

//电子围栏类型
enum EtcFenceType
{
	ForbidFly,        //禁飞区
	SafeArea,         //安全区
	NoDef             //无定义
};


class EtcFenceManager;

class EditAttributes;

typedef std::vector<PointXY> PointVec;

class GISManager
{
public:

	GISManager();

	~GISManager();

	//获得实例
	static GISManager* getInstance();

	//销毁函数
	static void DestroyObject();

	void  init();

	/*!
	brief:设置地图控件
	param:CMap1*
	*/
	void setMap(CMap1* pMap);

	//打开地图文件函数
	void Openlocalfile(CString file);
	CString GetFileType(CString file);
	CString GetFileName(CString file);

	void Redraw();

	//清除所有图层
	void RemoveAllLayers();

	/*!
	brief:清除某一图层
	param: shapeID图层号
	return:void
	*/
	void EraseShape(long& shapeID);

	/*!
	brief:创建空的点图层
	param:shpLayerID图层号,ptStyle点类型,drawColor绘制颜色
	param:ptSize点大小
	return:void
	*/
	void CreateEmptyPointShapefile(long &shpLayerID,mapWindow::tkDefaultPointSymbol ptStyle = mapWindow::tkDefaultPointSymbol::dpsSquare,
		const unsigned long drawColor = RGB(255,0,0), int ptSize = 20);

	/*!
	brief:创建空的面Shapefile图层
	param:layerHandle图层号,drawColor面轮廓颜色,fillColor面填充颜色
	param:fillTransparency透明度(0-255)
	return:void
	*/
	void CreateEmptyAreaShapfile(long& layerHandle, const unsigned long drawColor, const unsigned long& fillColor = RGB(0,100,100), 
		const float& fillTransparency = 60);

	/*!
	brief:创建空的shpfile线图层
	param:绘制颜色lineColor
	param:lineWidth线宽,默认为1
	param:引用,返回值,矢量图层ID号shpLayerID
	return:void
	*/
	void CreateEmptyLineShapfile(long &shpLayerID, const unsigned long lineColor, float lineWidth = 1, 
		mapWindow::tkDashStyle lineStyle = mapWindow::tkDashStyle::dsCustom);

	//功能:向shpfile图层中增加1个航点数据
	//输入:矢量图层ID号shpLayerID,shp类型shpType
	//      航点数据,经度—lon; 纬度—lat
	void AddOnePoint2Shapfile(const long shpLayerID, const int shpType, const double lon, const double lat);


	//功能:基于点矢量图层标绘目标点
	//输入:点图层名称drawLayerID
	//		点坐标,经度lon, 纬度lat
	//      点名称strPtName    
	//      标绘颜色strColor
	//      标绘字体颜色数值fontColor
	void DrawPointShapeLayer(long &drawLayerID, const double lon, const double lat,
		CString strPtName, const CString strColor, unsigned long fontColor);

	/*!
	brief:设置点的旋转角度
	param:shapeLayerID点图层
	param:rotation旋转角度
	*/
	void setPointRotation(const long& shapeLayerID, double rotation);

	/*!
	brief:设置标注的属性,在创建图层时,若需在该图层标注时使用
	param: shapeID图层ID号, fontSize标注字体大小,colorName颜色名字,fontColor标注字体颜色
	param: XOffset/YOffset标注位置偏移量
	return: void
	*/
	void SetLabelCategory(const long& shapeID, int fontSize = 12, CString colorName = _T("红色"), unsigned long fontColor = RGB(255,0,0), double XOffset = 0, double YOffset = 0);

	/*!
	brief:设置标注的属性,在创建图层时,若需在该图层标注时使用
	param: shapeID图层ID号, fontSize标注字体大小,colorName颜色名字,fontColor标注字体颜色
	param: XOffset/YOffset标注位置偏移量
	return: void
	*/
	void SetLabelCategory2(const long& shapeID, int fontSize = 12, unsigned long fontColor = RGB(255,0,0), 
		unsigned long frameBackColor = RGB(0,0,0), double XOffset = 0, double YOffset = 0);

	/*!
	brief:设置默认标注属性
	param:layerHandle,
	return:void
	*/
	void SetInnerLabelCategory(const long& layerHandle,int fontSize = 12, unsigned long fontColor = RGB(255,0,0), 
		double XOffset = 0, double YOffset = 0);

	/*!
	brief:绘制标注,先通过设置SetLabelCategory
	param: isAdd true表示追加false表示清除单绘,shapefileID图层ID号,labelName标注名称,lon、lat标注位置
	param:rotation旋转角度,labalCatIndex使用label属性
	return: void
	*/
	void drawLabel(bool isAdd, const long& shapefileID, const CString& labelName, const double& lon, const double& lat, 
		const double& rotation = 0, const long& labalCatIndex = 0);

	/*!
	brief:根据经纬度、角度计算某物体多边形点地理坐标
	param:lon lat yaw经纬度和角度
	param:pArrayData地理坐标二维数组,pvec物体形状像素点数组
	*/
	void CalculatePolygonCoordinate(const double lon, const double lat, const double yaw, 
		double (*pArrayData)[2], const std::vector<PtPixel>& pvec);

	/*!
	brief:清除某一图层的shape
	param:shapeLayerID图层号
	ruturn: void
	*/
	void clearShapefileShape(const long& shapeLayerID);


	/*!
	brief:获取图层中图元的索引号
	param:layerHandle图层号,elementID元素ID,sel选择默认0
	return:long
	*/
	long getLayerShapeIndex(const long& layerHandle, const int& elementID, const int& sel = 0);

	/*!
	brief:根据图层中索引号获取元素ID
	param:layerHandle图层号,shapeIndex图元索引,sel选择默认0
	return:long
	*/
	int getLayerShapeEleID(const long& layerHandle, const long& shapeIndex, const int& sel = 0);

	/*!
	brief:删除图层图元
	param:layerhandle图层号,shapeIndex图元号
	return:bool
	*/
	bool deleteShape(const long& layerHandle, const long& shapeIndex);

	/*!
	brief:更改线图元的显示
	param:layerHandle图层号,shapeIndex图元索引号
	param:lineColor线颜色,lineWidth线宽度,线样式
	*/
	void changeLayerShapeLineStyle(const long& layerHandle, const long& shapeIndex, const CString& styleName, unsigned long lineColor,float lineWidth = 1,
		mapWindow::tkLineStipple lineStyle = mapWindow::tkLineStipple::lsDashed);

	/*!
	brief:更改面图元的样式
	param:layerHandle图层号,shapeIndex图元索引号
	param:styleName样式名称,drawColor边线颜色,fillColor填充颜色
	param: fillTransparency填充透明度,fillType填充类型
	return:void
	*/
	void changeAreaLayerShapeStyle(const long& layerHandle, const long& shapeIndex, const CString& styleName, const unsigned long drawColor, 
		const unsigned long& fillColor, const float& fillTransparency);

	/*!
	brief:更改图元某属性字段值
	param:layerhandle图层号,shapeIndex图元索引号, fieldName属性字段名称,value新属性字段值
	return:void
	*/
	void editAttributeValue(const long& layerHandler, const long& shapeIndex, const CString& fieldName, const CString& value);

	/*!
	brief:根据点击位置选中图元,并返回图元索引号
	param:layerHandle图层号,x y点击位置, x2 y2拉框时右下角位置
	param:选择模式
	return:long返回图元索引
	*/
	long selectShape(const long& layerHandle, long x, long y, long x2 = -1, long y2 = -1, bool isPt = false,
		mapWindow::SelectMode selectMode = mapWindow::SelectMode::INCLUSION);

	/*!
	brief:根据框选范围选中图元,并返回图元索引号
	param:layerHandle图层号,x1 y1框选左上角位置,x2 y2框选右上角位置
	param:selectedIndexVec返回的图元索引集合
	return:void
	*/
	void selectShapes(const long& layerHandle, long x1, long y1, long x2, long y2, std::vector<long>& selectedIndexVec);

	/*!
	brief:点选选中面图元(若有重叠,选择最小面积的)
	param:x,y点击位置
	return:long
	*/
	long selectAreaShape(const long& layerHandle, long x, long y);

	/*!
	brief:释放图层上所有被选中的图元
	parma:图层索引号
	return:void
	*/
	void releaseSelected(const long& layerHandle);

	/*!
	brief:根据一个点计算一个地域范围(地理长度为正方形)
	param:x y点位置,lenOfSide边长, extents返回值
	return:void
	*/
	void calculateExtents(const double& x, const double& y, double lenOfSide, mapWindow::IExtentsPtr extents);

public:

	CMap1* m_map;

	//是否打开地图
	bool m_bHaveAddMap;

	//地图空间句柄
	CWnd*  m_pMapCwnd;

	/*!电子围栏管理器*/
	EtcFenceManager* m_etcFenceManager;

	/*!属性显示编辑类*/
	EditAttributes* m_editAttributes;

private:

	static GISManager* m_gisMananger;             //静态变量
	static int m_iCounter;         
};

#endif