#define _IN_GEOD_SET

#include <math.h>
#include <stdlib.h>
#include <string.h>

#include "proj.h"
#include "proj_internal.h"
#include "geod_interface.h"
#include "emess.h"

	void
geod_set(int argc, char **argv) {
	paralist *start = nullptr, *curr;
	double es;
	char *name;

    /* put arguments into internal linked list */
	if (argc <= 0)
		emess(1, "no arguments in initialization list");
	start = curr = pj_mkparam(argv[0]);
	if (!curr)
		emess(1, "memory allocation failed");
	for (int i = 1; curr != nullptr && i < argc; ++i) {
		curr->next = pj_mkparam(argv[i]);
		if (!curr->next)
			emess(1, "memory allocation failed");
		curr = curr->next;
	}
	/* set elliptical parameters */
	if (pj_ell_set(pj_get_default_ctx(),start, &geod_a, &es)) emess(1,"ellipse setup failure");
	/* set units */
	if ((name = pj_param(nullptr,start, "sunits").s) != nullptr) {
            bool unit_found = false;
            auto units = proj_get_units_from_database(nullptr, nullptr, "linear", false, nullptr);
            for( int i = 0; units && units[i]; i++ )
            {
                if( units[i]->proj_short_name &&
                    strcmp(units[i]->proj_short_name, name) == 0 ) {
                    unit_found = true;
                    to_meter = units[i]->conv_factor;
                    fr_meter = 1 / to_meter;
                }
            }
            proj_unit_list_destroy(units);
            if( !unit_found )
                emess(1,"%s unknown unit conversion id", name);
	} else
		to_meter = fr_meter = 1;
	geod_f = es/(1 + sqrt(1 - es));
	geod_ini();
	/* check if line or arc mode */
	if (pj_param(nullptr,start, "tlat_1").i) {
		double del_S;
		phi1 = pj_param(nullptr,start, "rlat_1").f;
		lam1 = pj_param(nullptr,start, "rlon_1").f;
		if (pj_param(nullptr,start, "tlat_2").i) {
			phi2 = pj_param(nullptr,start, "rlat_2").f;
			lam2 = pj_param(nullptr,start, "rlon_2").f;
			geod_inv();
			geod_pre();
		} else if ((geod_S = pj_param(nullptr,start, "dS").f) != 0.) {
			al12 = pj_param(nullptr,start, "rA").f;
			geod_pre();
			geod_for();
		} else emess(1,"incomplete geodesic/arc info");
		if ((n_alpha = pj_param(nullptr,start, "in_A").i) > 0) {
			if ((del_alpha = pj_param(nullptr,start, "rdel_A").f) == 0.0)
				emess(1,"del azimuth == 0");
		} else if ((del_S = fabs(pj_param(nullptr,start, "ddel_S").f)) != 0.) {
			n_S = (int)(geod_S / del_S + .5);
		} else if ((n_S = pj_param(nullptr,start, "in_S").i) <= 0)
			emess(1,"no interval divisor selected");
	}
	/* free up linked list */
	for ( ; start; start = curr) {
		curr = start->next;
		free(start);
	}
}
