#include <string.h>
#include <ctype.h>
#include <math.h>
#include <glib/gprintf.h>
#include "globals.h"
#include "string_utils.h"

#include "lcd.h"  // FIXME


void Float_To_Text(int decimal_digits,float number_in, gchar ** text_out)
{
	g_assert (*text_out == NULL);

	if (fabs(number_in)<1.1*smallest_allowed_number) {
		if (number_in<0.0) {
			*text_out = g_strdup_printf("-0.%0*d",decimal_digits,0);
		} else {
			*text_out = g_strdup_printf("0.%0*d",decimal_digits,0);
		}
		return;
	}

	*text_out = g_strdup_printf("%.*e", decimal_digits, number_in);
}


gboolean String_is_it_numeric(char *parameter)
{

	GRegex *numeric_regex = g_regex_new (	"\\s*[+-]?(\\d*\\.\\d+|\\d+(\\.\\d*)?)\\s*(e\\s*[+-]?\\d+)?\\s*",
	                                        G_REGEX_CASELESS,
	                                        0,
	                                        NULL);

	gboolean match = g_regex_match (numeric_regex, parameter, 0, NULL);
	g_regex_unref (numeric_regex);
	return match;
}


void String_Parameter_To_Text(float Float_To_Convert,int Int_To_Convert, int significant_digits,
                              char *start_string,char *units,char *LCD_string,int show_plus_sign)
{
	// FIXME - crappy string func
	char out_val[LCD_col_width+1];
	char floating_val[32];
	char String_of_spaces[LCD_col_width+1];
	char unit_mult[10];	/* units multiplier, eg. M, k, u */

	int i;						/* just a counter */
	int shift_decimal_by;		/* if the exponent isn't a multiple of 3, the decimal point will be moved */
	int decimal_location;		/* where the decimal is in the number string */
	int chars_processed;		/* how many characters are in the parsed number string so far */

	int exponent_val;			/* the exponent, in integer form */

	/* Copy the floating point value to a string. Do not multiply to accomodate units; the roundoff */
	/* is annoying. (e.g. 1.000 -> 0.999) */
	/* Move the decimal with string manipulations instead. */

	strcpy(LCD_string,start_string);

	/* if significant_digits is zero, used the supplied integer rather than the floating number */

	if (!significant_digits) {
		sprintf(out_val, "%d", (int) Float_To_Convert);
		strcat(LCD_string,out_val);
	} else {
		Float_To_Text(remote_digits_after_decimal,Float_To_Convert,floating_val);

		/* -- COPY FIRST ONE OR TWO CHARACTERS -- */
		if (floating_val[0]=='-') {		/* if it's negative ... */
			decimal_location=2;				/* decimal at position two (e.g.: -2.23e-9) */
			chars_processed=2;				/* two characters so far (e.g.: -2) */
			out_val[0]='-';					/* copy minus sign */
			out_val[1]=floating_val[1];	/* copy first digit */
		} else if (show_plus_sign==YES) {	/* if it's positive and plus sign required ... */
			decimal_location=1;				/* decimal at position one (e.g.: 2.23e-9) */
			chars_processed=2;				/* two characters so far (e.g.: +2) */
			out_val[0]='+';					/* add plus sign */
			out_val[1]=floating_val[0];	/* copy first digit */
		} else {									/* if it's positive and plus sign not required ... */
			decimal_location=1;				/* decimal at position one (e.g.: 2.23e-9) */
			chars_processed=1;				/* one character so far (e.g.: 2) */
			out_val[0]=floating_val[0];	/* copy first digit */
		}

		/* -- FIND EXPONENT -- */
		/* find how much the decimal has to be moved, by examining the exponent in the string and */
		/* modding it by 3 */
		exponent_val = atoi(floating_val+strlen(floating_val)-3);	/* read the last three characters */
		/* e.g. +09, or -07 */

		shift_decimal_by=(300+exponent_val) % 3;	/* added 300 to keep everything positive */

		/* -- PICK UNITS -- */
		if (exponent_val<12 && exponent_val>=9) {
			strcpy(unit_mult,"G");
		} else if (exponent_val<9 && exponent_val>=6) {
			strcpy(unit_mult,"M");
		} else if (exponent_val<6 && exponent_val>=3) {
			strcpy(unit_mult,"k");
		} else if (exponent_val<3 && exponent_val>=0) {
			strcpy(unit_mult,"");
		} else if (exponent_val<0 && exponent_val>=-3) {
			strcpy(unit_mult,"m");
		} else if (exponent_val<-3 && exponent_val>=-6) {
			strcpy(unit_mult,"u");
		} else if (exponent_val<-6 && exponent_val>=-9) {
			strcpy(unit_mult,"n");
		} else if (exponent_val<-9 && exponent_val>=-12) {
			strcpy(unit_mult,"p");
		}

		if (exponent_val<-12) {
			strcpy(unit_mult,"");   /* if parameter=0, don't use silly units */
		}

		/* -- MOVE DIGITS AROUND DECIMAL POINT -- */

		/* move the digits that will come before the decimal */
		for (i=decimal_location; i<decimal_location+shift_decimal_by; ++i) {
			out_val[chars_processed]=floating_val[1+i];
			++chars_processed;
		}

		/* put in the new decimal point */
		out_val[chars_processed]='.';
		++chars_processed;

		/* copy the rest of the digits */
		for (i=shift_decimal_by+1+decimal_location; i<significant_digits+3; ++i) {
			out_val[chars_processed]=floating_val[i];
			++chars_processed;
			/* leave space for minus sign, decimal point, and extra digit on the end too */
		}

		/* -- TERMINATE STRING -- */
		if ((show_plus_sign==YES) || (floating_val[0]=='-')) {
			out_val[significant_digits+3]=0;
		} else {
			out_val[significant_digits+2]=0;
		}


		/* -- FINISH UP -- */

		strcat(LCD_string,out_val);
		LCD_string[strlen(LCD_string)-1]=0;	/* remove extra digit */

		/* -- CHECK FOR TERMINATING DECIMAL POINT -- */
		if (LCD_string[strlen(LCD_string)-1]=='.') {
			LCD_string[strlen(LCD_string)-1]=0;
		}

		strcat(LCD_string,unit_mult);
	}

	strcat(LCD_string,units);
}