/***********************************
 * Update histories:
 * 
 * v1.4.1
 * 1. Add minimal resolution and max depth controls for the topography constrain.
 * 2. Add data format and update history sections in help information.
 * 
 ***********************************/

#include "stt_class.h"

void disp_help(char* proname, bool show_all){
	string exe_name = proname;
	exe_name = " " + exe_name + 
" -d<minimal-depth>/<maximal-depth> \
[-r'WGS84'|'Earth'|'Moon'|<equator-radius>/<pole-radius>|<equator_radius>,<flat-rate>] \
[-o<orient-longitude>/<orient-latitude>] \
[-m<output-msh-file>] \
[-v<output-vert-loc-file>] \
[-t<output-tri-cen-file>] \
[-n<output-tri-neg-file>] \
[-p<control-point-file>] \
[-l<control-line-file>] \
[-g<control-poly-filen>] \
[-c<control-circle-file>] \
[-s<outline-shape-file>] \
[-k<hole-shape-file>] \
[-z<control-topography-file>] \
[-h]";
	clog << "       _    _   \n";
	clog << "  ___ | |_ | |_ \n";
	clog << " / __|| __|| __|\n";
	clog << " \\__ \\| |_ | |_ \n";
	clog << " |___/ \\__| \\__|\n";
	clog << proname << " - v1.4.1 - A generator of the Spherical Triangular Tessellation (STT).\n\
This program is distributed under a dual licensing scheme. It is free for academic use, but a commercial license is required for commercial use.\n\n";
	clog << "Author: Dr. Yi Zhang (yizhang-geo@zju.edu.cn)\n\n";
	clog << "Usage: " << exe_name << endl << endl;
	clog << "Options:" << endl;
	clog << "\t-d\tMinimal and maximal quad-tree depths of the output STT." << endl;
	clog << "\t-r\tCoordinate reference system of the output STT, the default is 1e+5/1e+5." << endl;
	clog << "\t-o\tOrientation of the top vertex of the base icosahedron, the default is 0/90." << endl;
	clog << "\t-m\tOutput Gmsh(.msh) filename." << endl;
	clog << "\t-v\tOutput vertex location(.txt) filename." << endl;
	clog << "\t-t\tOutput triangle center location(.txt) filename." << endl;
	clog << "\t-n\tOutput triangle neighbor(.txt) filename." << endl;
	clog << "\t-p\tInput control point location(.txt) filename." << endl;
	clog << "\t-l\tInput control line location(.txt) filename." << endl;
	clog << "\t-g\tInput control polygon location(.txt) filename." << endl;
	clog << "\t-c\tInput control circle location(.txt) filename." << endl;
	clog << "\t-s\tInput outline polygon location(.txt) filename." << endl;
	clog << "\t-k\tInput hole polygon location(.txt) filename." << endl;
	clog << "\t-z\tInput topography(.txt) filename." << endl;
	clog << "\t-h\tShow full help information." << endl;

	if (!show_all) return;

	clog << R"(
Input File Formats:

1. Point Control Format
Controls refinement around specific points. Each point is defined by its location and refinement parameters:

# <longitude> <latitude> <maximal-depth> <minimal-resolution> <physical-group>
# longitude, latitude: Coordinates in degrees
# maximal-depth: Maximum refinement depth for this point
# minimal-resolution: Minimum cell size in degrees
# physical-group: Group identifier for the refined region
-45 -45 5 1.0 7
45 -45 5 1.0 7

2. Circle Control Format
Controls refinement around spherical caps. Each circle is defined by its center, radius, and refinement parameters:

# <longitude> <latitude> <spherical-cap-degree> <maximal-depth> <minimal-resolution> <physical-group>
# spherical-cap-degree: Angular radius of the cap in degrees
45 60 30 5 0.1 12
-20 -45 20 6 0.1 13

3. Line/Polygon Control Format
Controls refinement along lines or around polygons. Each shape is defined by a sequence of points and refinement parameters:

# First line: <number-of-points> <maximal-depth> <minimal-resolution> <physical-group>
# Following lines: <longitude> <latitude> of each point
# Points are connected in sequence, last point connects to first for polygons
4 6 0.1 5
-10 10
50 15
60 55
-15 50

4. Topography Control Format
Controls refinement based on elevation data. The refinement is based on elevation variation within triangles:

# First line: STD|MAX <maximal-depth> <minimal-resolution> <physical-group> [<maximum-STD>]
# Following lines: <longitude> <latitude> <elevation(meters)>
# maximum-STD: Maximum allowed standard deviation of elevation within a triangle
STD 10 -1 5 200.0
-179.95 89.95 -4203.20
-179.85 89.95 -4203.07
-179.75 89.95 -4203.47

Note: maximum-STD represents the maximum standard deviation of elevation allowed in a triangle. A triangle will be refined if the elevation variation within it exceeds this threshold.)" << std::endl;
	return;
}

int main(int argc, char* argv[]){
	/*map of input options
	0 -> tree depths
	1 -> coordinate reference system
	2 -> orientation of the base icosahedron
	3 -> output filename for the constructed model (Gmsh .msh file)
	4 -> output filename for vertex locations
	5 -> output filename for triangle's center locations
	6 -> output filename for triangle's neighboring index
	7 -> input filename for point constraints
	8 -> input filename for line constraints
	9 -> input filename for polygon constraints
	10-> input filename for circle constraints
	11-> input filename for outline shape constraints
	12-> input filename for hole shape constraints
	13-> input filename for topography constraints*/
	char input_options[14][1024];
	for (int i = 0; i < 14; i++){
		strcpy(input_options[i],"NULL");
	}

	// show help information is no options is read
	if (argc == 1){
		disp_help(argv[0], false);
		return 0;
	}

	int curr, option_number;
	while((curr = getopt(argc,argv,"hd:r:o:m:v:t:n:p:l:g:c:s:k:z:")) != -1){
		// get option number
		switch (curr){
			case 'h': // show help information
				disp_help(argv[0], true); return 0;
			case 'd':
				option_number = 0; break;
			case 'r':
				option_number = 1; break;
			case 'o':
				option_number = 2; break;
			case 'm':
				option_number = 3; break;
			case 'v':
				option_number = 4; break;
			case 't':
				option_number = 5; break;
			case 'n':
				option_number = 6; break;
			case 'p':
				option_number = 7; break;
			case 'l':
				option_number = 8; break;
			case 'g':
				option_number = 9; break;
			case 'c':
				option_number =10; break;
			case 's':
				option_number =11; break;
			case 'k':
				option_number =12; break;
			case 'z':
				option_number =13; break;
			case '?': //处理未定义或错误参数
				if (optopt == 'd' || optopt == 'r' || optopt == 'o' || optopt == 'm' || optopt == 'n'
					|| optopt == 'v' || optopt == 't' || optopt == 'p' || optopt == 'l'
					|| optopt == 'g' || optopt == 'c' || optopt == 's' || optopt == 'k'
					|| optopt == 'z'){
					fprintf (stderr, "Option -%c requires an argument.\n", optopt);
					return 0;
				}
				else if (isprint(optopt)){
					fprintf (stderr, "Unknown option `-%c'.\n", optopt);
					return 0;
				}
				else{
					fprintf (stderr,"Unknown option character `\\x%x'.\n",optopt);
					return 0;
				} break;
			default:
				abort();
		}

		if (1!=sscanf(optarg,"%s",input_options[option_number])){
			cerr<<BOLDRED<<"Error ==> "<<RESET<<"bad syntax: "<<optarg<<endl;
			return 0;
		}
	}

	SttGenerator instance;
	// record commands
	instance.set_command_record(argc,argv);
	// generate stt model
	instance.Routine(input_options);
	return 0;
}