#pragma once
#include <complex>
#include <Eigen/Core>
#include <Eigen/Dense>
#include <omp.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <gdal.h>
#include <gdal_utils.h>
#include <gdal_priv.h>
#include <gdalwarper.h>
#include <proj.h>
#include <string.h>
#include <memory.h>
#include <memory>
#include <vector>
#include "referenceHeader.h"
#include "BaseToollib/GeoOperator.h"


/**
*  此类用于FEKO的基本类型，主要功能如下：
*  1. 根据分辨率、中心频率、带宽，近远斜距，计算频率起始点，以及采样点数
*  2. 根据起始成像点、成像时长、PRF采样点数，获取PRF采样点数
*  3. 结合 PRF采样点坐标，入射角，以及与飞行方向的夹角（默认为 90度）, 参考高程，计算入射波的参考平面部分
*  4.
***/

namespace FEKOBase {

	//==========================================================
	// FEKO常用坐标系
	//==========================================================
	enum FEKOCoordinateSystem {
		Spherical, // 球坐标系
		Cartesian, // 笛卡尔坐标系
		UNKONWFEKOCOORDINATESYSTEM // 必须为最后一个表示未知
	};
	FEKOBase::FEKOCoordinateSystem FEKOCoordinateSystemString2Enum(QString str);
	QString QString2FEKOCoordinateSystem(FEKOBase::FEKOCoordinateSystem mode);


	//==========================================================
	// FEKO成像模式枚举
	//==========================================================
	enum FEKOImageMode
	{
		Strip,
		Scane,
		ISAR,
		CircleSAR,
		UNKNOW
	};

	FEKOImageMode FEKOImageModeString2Enum(QString str);
	QString FEKOImageModeenumToString(FEKOImageMode mode);




	//==========================================================
	// FEKO成像仿真参数类，主要用来搭建统一的仿真成像模块
	//==========================================================




	//==========================================================
	// 频率参数
	//==========================================================
	struct freqParams { // 频率参数
		double startfreqs;
		double endfreqs;
		size_t freqpoint;
	};

	//==========================================================
	// 输入的卫星参数
	//==========================================================
	struct SatellitePosition { // 卫星姿态
		double Px = 0, Py = 0, Pz = 0;
	};
	struct SatelliteVelocity { // 卫星速度
		double Vx = 0, Vy = 0, Vz = 0;
	};

	struct SatelliteState { // 卫星矢量
		SatellitePosition pos;
		SatelliteVelocity vel;
	};


	//==========================================================
	// FEKO 远场等效源姿态参数
	//==========================================================
	struct FEKOantPitionDirect {
		double x = 0;
		double y = 0;
		double z = 0;
		double theta = 0;
		double phi = 0;
	};


	//===========================================================
	// FEKO成像设置参数
	//===========================================================
	struct FEKOImageSettingParams {
		double min_x = 0;
		double max_x = 0;
		double min_y = 0;
		double max_y = 0;
		double plane_z = 0; // 平面高程
		size_t ImageWidth = 0;
		size_t ImageHeight = 0;
		
	};



	//==========================================================
	// FEKO参数文件等效参数
	//==========================================================
	struct FEKOSatelliteParams { // FEKOPRF脉冲参数
		size_t PRFidx = 0; // PRF 脉冲计数
		SatelliteState pose;// 卫星矢量
		double incidenceAngle = 0; // 入射角
		double AzAngle = 0; // 姿态角
		FEKOantPitionDirect antpos;// 天线实际姿态
		bool isRight = false; // 判断左右视，false 左，right 右
	};


	/////////////////////////////////////////////////
	///// 函数类
	//////////////////////////////////////////////
	/// <summary>
	///  频率Setting
	/// </summary>
	/// <param name="centerFreq">中心频率 GHZ</param>
	/// <param name="resolution">分辨率 米</param>
	/// <param name="bandWidth">带宽 GHz</param>
	/// <param name="scenceRange">分辨率 米</param>
	/// <param name="isResolution"></param>
	/// <returns></returns>
	freqParams getFreqSetting(double centerFreq, double resolution, double bandWidth, double scenceRange, bool isResolution = false);

	FEKOSatelliteParams createFEKOSatelliteParams(double Px, double Py, double Pz, double Vx, double Vy, double Vz, double incidenceAngle, double AzAngle, double theta, double phi, bool isRight, size_t PRFIdx = 0);
	FEKOSatelliteParams createFEKOSatelliteParams(SatelliteState pose, double incidenceAngle, double AzAngle, FEKOantPitionDirect antpos, size_t PRFIdx = 0);

	SatelliteState FEKOSatelliteParams2SatelliteState(FEKOSatelliteParams parmas);
	FEKOantPitionDirect FEKOSatelliteParams2FEKOantPitionDirect(FEKOSatelliteParams parmas);

	/// <summary>
	/// 将卫星姿态转换为 FEKO 天线坐标，
	/// 注意默认模型的Z轴为天线的指向
	/// </summary>
	/// <param name="satepos">卫星矢量</param>
	/// <param name="incidenceAngle">入射角</param>
	/// <param name="AzAngle">侧视角</param>
	/// <param name="isRIGHT">是否为右视</param>
	/// <param name="antposition_Direct">结果文件</param>
	/// <param name="inDs">输入模型</param>
	/// <returns></returns>
	TopoDS_Shape SatellitePos2FEKOAntPos(SatelliteState satepos, double incidenceAngle, double AzAngle, bool isRIGHT, FEKOantPitionDirect* antposition_Direct, TopoDS_Shape inDs);



	//===============================================
	// FEKO结果解析文件
	//===============================================		

	struct ElectricFieldData {
		QString fileType;
		QString fileFormat;
		QString source;
		QString date;
		double radius;
		double theta;
		double phi;
		double reEr;
		double imEr;
		double reEtheta;
		double imEtheta;
		double reEphi;
		double imEphi;
		QString configurationName;
		QString requestName;
		double frequency;
		QString coordinateSystem;
		Point_3d origin;
		int numRadiusSamples;
		int numThetaSamples;
		int numPhiSamples;
		QString resultType;
		int numHeaderLines;
		size_t prfidx = -1; // 脉冲计数，>0
	};

	struct PRFPluseData { // 单个PRF脉冲数据格式
		size_t prfidx; //脉冲次数
		double freqstart;
		double freqend;
		size_t freqpoints;

		double px, py, pz;
		//double theta, phi;
		//double incidence, azangle;
		//std::vector<double> freqlist;
		std::vector<ElectricFieldData> electricFieldDataList; // 单频点信息
	};

	bool compareElectricFieldDataInFreq(const ElectricFieldData& a, const ElectricFieldData& b);
	bool comparePRFPluseDataInPRFIdx(const PRFPluseData& a, const PRFPluseData& b);

	class NearFieldEchoCSVParser {
	public:
		NearFieldEchoCSVParser();
		~NearFieldEchoCSVParser();
	private:
		bool usePRFCountMode = true;
		//std::vector<ElectricFieldData> electricFieldDataList;
		QMap<QString, std::vector<ElectricFieldData>> electricFieldDataList; // 电场数据
		//QMap<QString, PRFPluseData> prfPluseMap;
		std::vector<PRFPluseData> prfData;
		size_t freqPoints;
		double freqStart;
		double freqEnd;
		// 频率参数
	private: // 内部检查函数
		bool checkPRFModel();
		bool resizePRFPluse(); //回波整理

	public:
		bool parseCSV(const QString& filePath); // 读取回波数据文件
		void toThetapolar(const QString& filePath);// 输出theta 极化
		void toPhiPolar(const QString& filePath);// 输出phi 极化
		void toRPolar(const QString& filePath);// 输出phi 极化
		void saveCSV(const QString& filePath);// 输出csv文件
	private:
		void toEchoData(const QString& filePath, size_t outDataName);// 输出回波数据
	};




	//========================================================================
	// 成像回波格式
	// file type:
	// freqStart,freqEnd,freqPoint,isRight,
	// PRF1,Pos,incidenceAngle,AzAngle,echoDatalist
	// PRF2,Pos,incidenceAngle,AzAngle,echoDatalist
	// 。
	// 。
	// 。
	// 注意Bp并不关心脉冲的顺序，只是关注脉冲的坐标位置，默认按照脉冲的解析顺序进行组织
	//========================================================================
	class EchoDataClass {
	private: // 成像变量
		Eigen::MatrixXcd echoData; // 回波数据 
		Eigen::MatrixXd antPos;// 每个脉冲的坐标
		double freqStart; // 起始频率
		double freqEnd; // 终止频率
		int freqpoints; // 频率点数

	public:
		EchoDataClass(const FEKOBase::EchoDataClass& inecho);
		EchoDataClass();
		~EchoDataClass();
	public:
		// 根据每个成员变量构建属性
		void setEchoData(Eigen::MatrixXcd echoData);
		Eigen::MatrixXcd getEchoData() const;
		void setAntPos(Eigen::MatrixXd antPos);
		Eigen::MatrixXd getAntPos() const;
		void setFreqStart(double freqStart);
		double getFreqStart() const;
		void setFreqEnd(double freqEnd);
		double getFreqEnd() const;
		void setFreqpoints(int freqpoints);
		int getFreqpoints() const;

		void loadEchoData(const QString& filePath); // 加载回波数据文件
		void SaveEchoData(const QString& filePath); // 保存回波数据文件
	};





	//==========================================================
	// 仿真成像算法类
	// BP成像算法
	// 建议将所有的频率处理到 GHz 单位，避免频率过大导致的精度问题
	// 回波矩阵：
	// PRF1:f1,f2,f3,f4
	// PRF2：f1,f2,f3,f4
	// PRF2：f1,f2,f3,f4
	//==========================================================

	enum ImageAlgWindowFun  // 成像方法加窗方法
	{
		NOWINDOWS,
		HANMMING,
		UNKONWWINDOW
	};

	/// <summary>
	/// 加窗
	/// </summary>
	/// <param name="echo">行:脉冲，列：频点</param>
	/// <returns></returns>
	Eigen::MatrixXd WINDOWFun(Eigen::MatrixXcd& echo, ImageAlgWindowFun winfun = ImageAlgWindowFun::HANMMING);

	enum FEKOImageAlgorithm
	{
		TBP_TIME,
		TBP_FREQ,
		UNKONW // 必须为最后一个表示未知
	};

	QList<QString> getFEKOImageAlgorithmList();
	FEKOImageAlgorithm String2FEKOImageAlgorithm(QString str);
	QString FEKOImageAlgorithm2String(FEKOImageAlgorithm alg);

	// 请仿照FEKOImageAlgorithm枚举的写法，构建QString  与 ImageAlgWindowFun 的转换函数
	QList<QString> getImageAlgWindowFunList();
	ImageAlgWindowFun String2ImageAlgWindowFun(QString str);
	QString ImageAlgWindowFun2String(ImageAlgWindowFun alg);


	bool BPImage_TIME(QString& restiffpath, Eigen::MatrixXcd& echoData, Eigen::MatrixXd& antPos, Eigen::MatrixXd& freqmatrix, Eigen::MatrixXd& X, Eigen::MatrixXd& Y, Eigen::MatrixXd& Z, ImageAlgWindowFun winfun = ImageAlgWindowFun::HANMMING); // BP成像
	bool FBPImage_FREQ(QString& restiffpath, Eigen::MatrixXcd& echoData, Eigen::MatrixXd& antPos, Eigen::MatrixXd& freqmatrix, Eigen::MatrixXd& X, Eigen::MatrixXd& Y, Eigen::MatrixXd& Z, ImageAlgWindowFun winfun = ImageAlgWindowFun::HANMMING); // FBP成像

 

}