// SIMOrthoProgram.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
//#define EIGEN_USE_MKL_ALL
//#define EIGEN_VECTORIZE_SSE4_2
//#include <mkl.h>

#include <iostream>
#include <Eigen/Core>
#include <Eigen/Dense>
#include <time.h>
//#include <mkl.h>
#include <stdlib.h>
#include <direct.h>
// gdal
#include <proj.h>
#include <string>'
#include "gdal_priv.h"
#include "ogr_geometry.h"
#include "gdalwarper.h"
#include "baseTool.h"
#include "simptsn.h"
#include "test_moudel.h"
#include <Windows.h>
using namespace std;
using namespace Eigen;

//mode 1
void PreProcess(int argc, char* argv[])
{
	// .\baseTool\x64\Release\SIMOrthoProgram.exe 1 D:\MicroWorkspace\C-SAR\Ortho\Temporary\unpack\GF3_SAY_QPSI_013952_E118.9_N31.5_20190404_L1A_AHV_L10003923848\GF3_SAY_QPSI_013952_E118.9_N31.5_20190404_L1A_HH_L10003923848.tiff
	//输入参数
	std::cout << "==========================================================================" << endl;
	std::cout << "预处理计算结果，可以计算出DEM 范围" << endl;
	std::cout << "SIMOrthoProgram.exe 1  in_parameter_path  in_dem_path  in_ori_sar_path  in_work_path  in_taget_path ";
	std::string parameter_path = argv[2]; // 参数文件
	std::string dem_path = argv[3]; // dem 文件
	std::string in_sar_path = argv[4]; // 输入SAR文件
	std::string work_path = argv[5]; // 目标空间文件
	std::string taget_path = argv[6]; // 输出坐标映射文件
	//std::string Incident_path = argv[7];// 输出入射角文件

	std::cout << "==========================================================================" << endl;
	std::cout << "in parameters:========================================================" << endl;
	std::cout << "parameters file path:\t" << parameter_path << endl;
	std::cout << "input dem image(WGS84)" << dem_path << endl;
	std::cout << "the sar image:\n" << in_sar_path << endl;
	std::cout << "the work path for outputing temp file :\t" << work_path << endl;
	std::cout << "the out file for finnal file:\t" << taget_path << endl;
	simProcess process;
	std::cout << "==========================================================================" << endl;
	process.InitSimulationSAR(parameter_path, work_path, taget_path, dem_path, in_sar_path);
	std::cout << "==========================================================================" << endl;
}

//mode 2
void calIncident_localIncident_angle(int argc, char* argv[]) {

	std::cout << "mode 2: get incident angle and local incident angle by rc_wgs84 and dem and statellite model:\n";
	std::cout << "SIMOrthoProgram.exe 2  in_parameter_path  in_dem_path  in_rc_wgs84_path  out_incident_angle_path  out_local_incident_angle_path";

	std::string parameter_path = argv[2];
	std::string dem_path = argv[3];
	std::string in_rc_wgs84_path = argv[4];
	std::string out_incident_angle_path = argv[5];
	std::string out_local_incident_angle_path = argv[6];

	simProcess process;
	std::cout << "==========================================================================" << endl;
	PSTNAlgorithm pstn(parameter_path);
	std::cout << "==========================================================================" << endl;
	process.pstn = pstn;
	process.calcalIncident_localIncident_angle(dem_path, in_rc_wgs84_path, out_incident_angle_path, out_local_incident_angle_path, pstn);

}

// mode 3
void calInterpolation_cubic_Wgs84_rc_sar(int argc, char* argv[]) {

	std::cout << "mode 3: interpolation(cubic convolution) orth sar value by rc_wgs84 and ori_sar image and model:\n ";
	std::cout << "SIMOrthoProgram.exe 3  in_parameter_path  in_rc_wgs84_path  in_ori_sar_path  out_orth_sar_path";

	std::string parameter_path = "D:\\MicroSAR\\C-SAR\\Ortho\\Ortho\\Temporary\\package\\orth_para.txt"; argv[2];
	std::string in_rc_wgs84_path = "D:\\MicroSAR\\C-SAR\\Ortho\\Ortho\\Temporary\\dem_rc.tiff"; argv[3];
	std::string in_ori_sar_path = "D:\\MicroSAR\\C-SAR\\Ortho\\Ortho\\Temporary\\unpack\\GF3_MYN_QPSI_011437_E99.2_N28.6_20181012_L1A_AHV_L10003514912\\GF3_MYN_QPSI_011437_E99.2_N28.6_20181012_L1A_VV_L10003514912.tiff"; argv[4];
	std::string out_orth_sar_path = "D:\\MicroSAR\\C-SAR\\Ortho\\Ortho\\Temporary\\package\\GF3_MYN_QPSI_011437_E99.2_N28.6_20181012_L1A_VV_L10003514912_GTC_rpc_geo.tif"; argv[5];
	parameter_path = argv[2];
	in_rc_wgs84_path = argv[3];
	in_ori_sar_path = argv[4];
	out_orth_sar_path = argv[5];

	simProcess process;
	std::cout << "==========================================================================" << endl;
	PSTNAlgorithm pstn(parameter_path);
	process.pstn = pstn;
	std::cout << "==========================================================================" << endl;
	process.interpolation_GTC_sar(in_rc_wgs84_path, in_ori_sar_path, out_orth_sar_path, pstn);
}

// mode 4 处理 RPC的入射角
void getRPC_Incident_localIncident_angle(int argc, char* argv[]) {
	std::cout << "mode 4: get RPC incident and local incident angle sar model:";
	std::cout << "SIMOrthoProgram.exe 4 in_parameter_path in_dem_path  in_rpc_rc_path  out_rpc_dem_path  out_incident_angle_path  out_local_incident_angle_path";
	std::string parameter_path = argv[2];
	std::string in_dem_path = argv[3];
	std::string in_rpc_rc_path = argv[4];
	std::string out_rpc_dem_path = argv[5];
	std::string out_incident_angle_path = argv[6];
	std::string out_local_incident_angle_path = argv[7];

	simProcess process;
	std::cout << "==========================================================================" << endl;
	PSTNAlgorithm pstn(parameter_path);
	std::cout << "==========================================================================" << endl;

	process.CreateRPC_DEM(in_rpc_rc_path, in_dem_path, out_rpc_dem_path);
	process.calcalIncident_localIncident_angle(out_rpc_dem_path, in_rpc_rc_path, out_incident_angle_path, out_local_incident_angle_path, pstn);
}

//mode 5
void cal_ori_2_power_tiff(int argc, char* argv[]) {
	std::cout << "mode 5: convert ori tiff to power tiff:";
	std::cout << "SIMOrthoProgram.exe 5 in_ori_path out_power_path";
	std::string in_ori_path = argv[2];
	std::string out_power_path = argv[3];
	simProcess process;
	process.ori_sar_power(in_ori_path, out_power_path);

}

// mode 6
void cal_GEC_Incident_localIncident_angle(int argc, char* argv[]) {
	std::cout << "mode 6: get gec incident and local incident angle sar model:";
	std::cout << "SIMOrthoProgram.exe 6 in_parameter_path in_dem_path  in_gec_lon_lat_path  out_incident_angle_path  out_local_incident_angle_path";
	std::string parameter_path = argv[2];
	std::string dem_path = argv[3];
	std::string in_gec_lon_lat_path = argv[4];
	std::string out_incident_angle_path = argv[5];
	std::string out_local_incident_angle_path = argv[6];

	simProcess process;
	std::cout << "==========================================================================" << endl;
	PSTNAlgorithm pstn(parameter_path);
	std::cout << "==========================================================================" << endl;
	process.calGEC_Incident_localIncident_angle(dem_path, in_gec_lon_lat_path, out_incident_angle_path, out_local_incident_angle_path, pstn);
}

// mode 7
void RPC_inangle(int argc, char* argv[]) {
	std::cout << "mode 7: get rpc incident and local incident angle sar model:";
	std::cout << "SIMOrthoProgram.exe 7 in_parameter_path in_dem_path  in_gec_lon_lat_path  work_path taget_path  out_incident_angle_path  out_local_incident_angle_path";
	std::string parameter_path = argv[2];
	std::string dem_path = argv[3];
	std::string in_gec_lon_lat_path = argv[4];
	std::string work_path = argv[5];
	std::string taget_path = argv[6];
	std::string out_incident_angle_path = argv[7];
	std::string out_local_incident_angle_path = argv[8];
	std::string out_incident_angle_geo_path = argv[9];
	std::string out_local_incident_angle_geo_path = argv[10];
	simProcess process;
	//InitRPCIncAngle(std::string paras_path, std::string workspace_path, std::string out_dir_path, std::string in_dem_path, std::string in_rpc_lon_lat_path)
	std::cout << "==========================================================================" << endl;
	process.InitRPCIncAngle(parameter_path, work_path, taget_path, dem_path, in_gec_lon_lat_path, out_incident_angle_path, out_local_incident_angle_path, out_incident_angle_geo_path, out_local_incident_angle_geo_path);
	std::cout << "==========================================================================" << endl;
}

// mode 3
void calInterpolation_cubic_Wgs84_rc_sar_sigma(int argc, char* argv[]) {

	std::cout << "mode 3: interpolation(cubic convolution) orth sar value by rc_wgs84 and ori_sar image and model:\n ";
	std::cout << "SIMOrthoProgram.exe 3  in_parameter_path  in_rc_wgs84_path  in_ori_sar_path  out_orth_sar_path";

	std::string parameter_path = "D:\\MicroSAR\\C-SAR\\Ortho\\Ortho\\Temporary\\package\\orth_para.txt"; argv[2];
	std::string in_rc_wgs84_path = "D:\\MicroSAR\\C-SAR\\Ortho\\Ortho\\Temporary\\dem_rc.tiff"; argv[3];
	std::string in_ori_sar_path = "D:\\MicroSAR\\C-SAR\\Ortho\\Ortho\\Temporary\\unpack\\GF3_MYN_QPSI_011437_E99.2_N28.6_20181012_L1A_AHV_L10003514912\\GF3_MYN_QPSI_011437_E99.2_N28.6_20181012_L1A_VV_L10003514912.tiff"; argv[4];
	std::string out_orth_sar_path = "D:\\MicroSAR\\C-SAR\\Ortho\\Ortho\\Temporary\\package\\GF3_MYN_QPSI_011437_E99.2_N28.6_20181012_L1A_VV_L10003514912_GTC_rpc_geo.tif"; argv[5];
	parameter_path = argv[2];
	in_rc_wgs84_path = argv[3];
	in_ori_sar_path = argv[4];
	out_orth_sar_path = argv[5];

	simProcess process;
	std::cout << "==========================================================================" << endl;
	PSTNAlgorithm pstn(parameter_path);
	process.pstn = pstn;
	std::cout << "==========================================================================" << endl;
	process.interpolation_GTC_sar_sigma(in_rc_wgs84_path, in_ori_sar_path, out_orth_sar_path, pstn);
}

void createRPC_lon_lat(int argc, char* argv[]) {
	std::cout << "mode 8";
	std::cout << "SIMOrthoProgram.exe 8 in_rpc_tiff out_lon_lat_path";
	std::string in_rpc_tiff = argv[2];
	std::string in_dem_tiff = argv[3];
	std::string out_lon_lat_path = argv[4];
	
	simProcess process;
	//InitRPCIncAngle(std::string paras_path, std::string workspace_path, std::string out_dir_path, std::string in_dem_path, std::string in_rpc_lon_lat_path)
	std::cout << "==========================================================================" << endl;
	process.CreateRPC_refrenceTable(in_rpc_tiff, in_dem_tiff,out_lon_lat_path);
	std::cout << "==========================================================================" << endl;
}

void Scatter2Grid_lon_lat(int argc, char* argv[]) {
	std::cout << "mode 10";
	std::cout << "SIMOrthoProgram.exe 10 lon_lat_path  data_tiff  grid_path  space";
	std::string lon_lat_path = "D:\\MicroSAR\\C-SAR\\Ortho\\Ortho\\Temporary\\package\\RD_ori_sim.tif";
	std::string data_tiff = "D:\\MicroSAR\\C-SAR\\Ortho\\Ortho\\Temporary\\GF3_SAY_QPSI_013952_E118.9_N31.5_20190404_L1B_HH_L10003923848_db.tif";
	std::string grid_path = "D:\\MicroSAR\\C-SAR\\Ortho\\Ortho\\Temporary\\package\\GF3_SAY_QPSI_013952_E118.9_N31.5_20190404_L1B_HH_L10003923848__db.tif";
	double space = 5;

	lon_lat_path = argv[2]; 
	data_tiff = argv[3]; 
	grid_path = argv[4]; 
	space = stod(argv[5]);
	simProcess process;
	//InitRPCIncAngle(std::string paras_path, std::string workspace_path, std::string out_dir_path, std::string in_dem_path, std::string in_rpc_lon_lat_path)
	std::cout << "==========================================================================" << endl;
	process.Scatter2Grid(lon_lat_path, data_tiff, grid_path, space);
	std::cout << "==========================================================================" << endl;
}


string GetExePath()
{
	char szFilePath[MAX_PATH + 1] = { 0 };
	GetModuleFileNameA(NULL, szFilePath, MAX_PATH);
	/*
	strrchr:函数功能：查找一个字符c在另一个字符串str中末次出现的位置（也就是从str的右侧开始查找字符c首次出现的位置），
	并返回这个位置的地址。如果未能找到指定字符，那么函数将返回NULL。
	使用这个地址返回从最后一个字符c到str末尾的字符串。
	*/
	(strrchr(szFilePath, '\\'))[0] = 0; // 删除文件名，只获得路径字串//
	string path = szFilePath;
	return path;
}

/// <summary>
/// 初始化
/// </summary>
void initProjEnv() {
	PJ_CONTEXT* C;
	C = proj_context_create();
	std::cout << "========================== init PROJ ================================================" << endl;
	string exepath = GetExePath();
	char buffer[10240];
	int i;
	for (i = 0; i < exepath.length(); i++) {
		buffer[i] = exepath[i];
	}
	buffer[i] = '\0';

	const char* proj_share_path = buffer;
	proj_context_set_search_paths(C, 1, &proj_share_path);
	char* buf = nullptr;
	size_t sz = 0;

	if (_dupenv_s(&buf, &sz, "PROJ_LIB") == 0 && buf != nullptr)
	{
		printf("PROJ_LIB = %s\n", buf);
		std::string newEnv = "PROJ_LIB=" + std::string(buffer);
		_putenv(newEnv.c_str());
	}
	else {
		std::string newEnv = "PROJ_LIB=" + std::string(buffer);
		_putenv(newEnv.c_str());
	}

	if (_dupenv_s(&buf, &sz, "PROJ_LIB") == 0 && buf != nullptr)
	{
		std::cout << "after PROJ_LIB = " << buf << endl;
	}
	free(buf);
	std::cout << "========================================================================================" << endl;
}


int main(int argc, char* argv[])
{
	initProjEnv();
	//WGS84_J2000();
	cout << "test\t" << acos(-1) << endl;
	cout << getAngle(Landpoint{ -3421843,5089485,3630606 }, Landpoint{ -2609414,4763328,3332879 }) << endl;;
	Landpoint p2 = { -3421843,5089485,3630606 };   Landpoint p1 = { -2609414,4763328,3332879 };
	cout << getIncAngle(p2, p1) << endl;;
	std::cout << "program start:\t" << getCurrentTimeString() << endl;;
	int mode = 1;
	GDALAllRegister();
	if (argc == 1) { // 测试参数
		// 算法说明
		std::cout << "========================== description  ================================================" << endl;
		std::cout << "algorithm moudel:.exe [modeparamert] {otherParaments}" << endl;
		std::cout << "mode 1: Preprocess\n ";
		std::cout << "SIMOrthoProgram.exe 1  in_parameter_path  in_dem_path  in_ori_sar_path  in_work_path  in_taget_path  out_GEC_dem_path  out_GTC_rc_path  out_GEC_lon_lat_path  out_clip_dem_path" << endl;

		std::cout << "mode 2: get incident angle and local incident angle by rc_wgs84 and dem and statellite model:\n";
		std::cout << "SIMOrthoProgram.exe 2  in_parameter_path  in_dem_path  in_rc_wgs84_path  out_incident_angle_path  out_local_incident_angle_path";

		std::cout << "mode 3: interpolation(cubic convolution) orth sar value by rc_wgs84 and ori_sar image and model:\n ";
		std::cout << "SIMOrthoProgram.exe 3  in_parameter_path  in_rc_wgs84_path  in_ori_sar_path  out_orth_sar_path";

		std::cout << "mode 4: get RPC incident and local incident angle sar model:";
		std::cout << "SIMOrthoProgram.exe 4 in_parameter_path in_dem_path  in_rpc_rc_path  out_rpc_dem_path  out_incident_angle_path  out_local_incident_angle_path";

		std::cout << "mode 5: interpolation(cubic convolution) orth sar value by gec_lon_lat and dem and ori_sar image and  sar model:";
		std::cout << "SIMOrthoProgram.exe 5  in_parameter_path  in_gec_lon_lat_path  in_dem_path  in_sar_path  out_orth_sar_path";

		std::cout << "mode 6: get gec incident and local incident angle sar model:";
		std::cout << "SIMOrthoProgram.exe 6   in_parameter_path   in_dem_path    in_gec_lon_lat_path  out_incident_angle_path  out_local_incident_angle_path";
		if (mode == 10) {
			Scatter2Grid_lon_lat(argc, argv);
		}
		else {
			test_main(mode, "D:\\MicroSAR\\C-SAR\\Ortho\\Ortho\\Temporary");
		}
		//calInterpolation_cubic_Wgs84_rc_sar(argc, argv);
	}
	else if (argc > 1) { // 预处理模块

		std::cout << "=============================description  V2.0 =============================================" << endl;
		std::cout << "algorithm moudel:.exe [modeparamert] {otherParaments}" << endl;
		std::cout << "algorithm moudel:.exe [modeparamert] {otherParaments}" << endl;
		mode = stoi(argv[1]);
		if (mode == 0) {
			test_main(mode, argv[2]);
		}
		else if (mode == 1) {
			PreProcess(argc, argv);
		}
		else if (mode == 2) { // RPC 计算模块
			calIncident_localIncident_angle(argc, argv);
		}
		else if (mode == 3) {
			calInterpolation_cubic_Wgs84_rc_sar(argc, argv);
		}
		else if (mode == 4) {
			getRPC_Incident_localIncident_angle(argc, argv);
		}
		else if (mode == 5) {
			cal_ori_2_power_tiff(argc, argv);
		}
		else if (mode == 6) {
			cal_GEC_Incident_localIncident_angle(argc, argv);
		}
		else if (mode == 7) {
			RPC_inangle(argc, argv);
		}
		else if (mode == 8) {
			createRPC_lon_lat(argc, argv);
		}
		else if (mode == 9) {
			calInterpolation_cubic_Wgs84_rc_sar_sigma(argc, argv);
		}
		else if (mode == 10) {
			Scatter2Grid_lon_lat(argc, argv);
		}
	}
	GDALDestroy(); // or, DllMain at DLL_PROCESS_DETACH
	std::cout << "program over：\t" << getCurrentTimeString() << endl;
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件
