/*****************************************************************************/
/*  Klavaro - a flexible touch typing tutor                                  */
/*  Copyright (C) 2005, 2006, 2007, 2008 Felipe Castro                       */
/*  Copyright (C) 2009, 2010, 2011 Free Software Foundation                  */
/*                                                                           */
/*  This program is free software, licensed under the terms of the GNU       */
/*  General Public License as published by the Free Software Foundation,     */
/*  either version 3 of the License, or (at your option) any later version.  */
/*  You should have received a copy of the GNU General Public License        */
/*  along with this program.  If not, see .    */
/*****************************************************************************/
/*
 * Velocity exercise
 */
#include 
#include 
#include 
#include 
#include 
#include 
#include "auxiliar.h"
#include "main.h"
#include "translation.h"
#include "keyboard.h"
#include "tutor.h"
#include "velocity.h"
GList *word_list;
struct
{
	GList *list;
	gint len;
	gchar *name;
} dict;
extern gchar *OTHER_DEFAULT;
/*******************************************************************************
 * Interface functions
 */
gchar *
velo_get_dict_name ()
{
	return (dict.name);
}
void
velo_reset_dict ()
{
	g_list_free (dict.list);
	dict.list = NULL;
	dict.len = 0;
	g_free (dict.name);
	dict.name = NULL;
}
/**********************************************************************
 * Initialize the velo exercise window.
 */
void
velo_init ()
{
	gchar *wl_name;
	if (dict.len != 0)
		return;
	if (main_preferences_exist ("tutor", "word_list"))
	{
		wl_name = main_preferences_get_string ("tutor", "word_list");
		velo_init_dict (wl_name);
		g_free (wl_name);
	}
	if (dict.len == 0)
		velo_init_dict (NULL);
}
/**********************************************************************
 * Retrieves words from the dictionary.
 */
void
velo_init_dict (gchar * list_name)
{
	static gchar *word_buf = NULL;
	gchar *word;
	gchar *tmp_buf;
	gchar *tmp_name;
	gchar *tmp_code;
	gchar *dict_name;
	if (list_name && !g_str_equal (list_name, OTHER_DEFAULT) )
	{
		main_preferences_set_string ("tutor", "word_list", list_name);
		tmp_name = g_strconcat (main_path_user (), G_DIR_SEPARATOR_S, list_name, ".words", NULL);
		g_message ("loading dictionary: %s.words", list_name);
		dict_name = g_strdup (list_name);
	}
	else
	{
		main_preferences_remove ("tutor", "word_list");
		tmp_code = main_preferences_get_string ("interface", "language");
		tmp_name = g_strconcat (main_path_data (), G_DIR_SEPARATOR_S, tmp_code, ".words", NULL);
		g_message ("loading dictionary: %s.words", tmp_code);
		g_free (tmp_code);
		dict_name = g_strdup ("Default");
	}
	if (!g_file_test (tmp_name, G_FILE_TEST_IS_REGULAR))
	{
		g_free (tmp_name);
		tmp_name = trans_lang_get_similar_file_name (".words");
		g_message ("not found, loading from file:\n %s", tmp_name);
		gdk_beep ();
	}
	if (g_file_get_contents (tmp_name, &tmp_buf, NULL, NULL))
	{
		velo_reset_dict ();
		dict.name = dict_name;
		g_free (word_buf);
		word_buf = tmp_buf;
		g_print ("Tens of words:\n 0");
		while (*tmp_buf != '\0')
		{
			word = tmp_buf;
			for (;*tmp_buf != '\n' && *tmp_buf != '\0'; tmp_buf++)
				;
			dict.list = g_list_prepend (dict.list, word);
			dict.len++;
			if (dict.len % 10 == 0)
				g_print (" - %u", dict.len / 10);
			if (*tmp_buf == '\0')
				break;
			*tmp_buf++ = '\0';
		}
		g_print ("\n");
		g_message ("Dictionary loaded!\n\n");
	}
	else
	{
		g_free (dict_name);
		g_message ("could not open the file: %s", tmp_name);
		tmp_code = main_preferences_get_string ("interface", "language");
		if (g_str_equal (tmp_code, "C"))
			g_error ("something wrong, we must quit!");
		main_preferences_set_string ("interface", "language", "C");
		velo_init_dict (list_name);
		main_preferences_set_string ("interface", "language", tmp_code);
		g_free (tmp_code);
	}
	g_free (tmp_name);
}
/**********************************************************************
 * Draw random phrases with words selected from a 'discretionary'
 */
void
velo_draw_random_words ()
{
	gint i, j;
	gchar *word;
	struct PARAGRAPH
	{
		gchar *text;
		gsize size;
		gsize i;
	} par;
	par.size = 1024;
	par.text = g_new (gchar, par.size);
	for (i = 0; i < 4; i++)	/* 4 paragraphs per exercise */
	{		
		par.i = 0;
		for (j = 0; j < 20; j++) /* 20 words per paragraph */
		{		
			word = g_strdup (g_list_nth_data (dict.list, rand () % dict.len));
			if (j == 0)
				word[0] = g_ascii_toupper (word[0]);
			if (par.i + strlen (word) + 4 > par.size)
			{
				par.size += 1024;
				par.text = g_renew (gchar, par.text, par.size);
			}
			strcpy (par.text + par.i, word);
			par.i += strlen (word);
			par.text[par.i++] = ' ';
			g_free (word);
		}
		par.i--;
		if (trans_lang_has_stopmark ())
			par.text[par.i++] = '.';
		par.text[par.i++] = '\n';
		par.text[par.i++] = '\0';
		tutor_draw_paragraph (par.text);
	}
	g_free (par.text);
}
/**********************************************************************
 * Takes text and make a list of words, one per line, validating as UTF-8
 */
gchar *
velo_filter_utf8 (gchar * text)
{
	gunichar uch;
	gboolean is_searching_word;
	struct INPUT_TEXT
	{
		gchar *pt;
		gulong len;
		guint nwords;
	} raw;
	struct FILTERED_TEXT
	{
		gchar *txt;
		gulong i;
		gulong len;
	} flt;
	raw.len = strlen (text);
	/* Verify empty string
	 */
	if (raw.len == 0)
	{
		flt.txt = g_strdup ("01234\n56789\n43210\n98765\n:-)\n");
		return (flt.txt);
	}
	/* Allocate memory space for the result
	 */
	flt.i = 0;
	flt.len = raw.len + 1024;
	flt.txt = g_malloc (flt.len);
	raw.pt = text;
	/* Filter
	 */
	raw.nwords = 0;
	is_searching_word = TRUE;
	while (raw.pt && raw.nwords < MAX_WORDS)
	{
		if (*raw.pt == '\0')
			break;
		/* Read valid utf8 char
		 */
		if ((uch = g_utf8_get_char_validated (raw.pt, -1)) == (gunichar) - 1
		    || uch == (gunichar) - 2)
			uch = L' ';
		/* Increase the pointer for the input text
		 */
		raw.pt = g_utf8_find_next_char (raw.pt, NULL);
		/* Verify memory space of output buffer
		 */
		if (flt.i < flt.len - 8)
		{
			flt.len += 1024;
			flt.txt = g_realloc (flt.txt, flt.len);
		}
		/* Test alphabetic char to form a word
		 */
		if (g_unichar_isalpha (uch))
		{
			flt.i += g_unichar_to_utf8 (uch, &flt.txt[flt.i]);
			is_searching_word = FALSE;
		}
		else if (!is_searching_word)
		{
			raw.nwords++;
			flt.txt[flt.i++] = '\n';
			is_searching_word = TRUE;
		}
	}
	flt.txt[flt.i++] = '\0';
	if (raw.nwords == 0)
	{
		g_free (flt.txt);
		flt.txt = g_strdup ("01234\n56789\n43210\n98765\n:-)\n");
	}
	return (flt.txt);
}
/**********************************************************************
 * Reads the text "text_raw" and write to the dictionary.
 * If overwrite is TRUE, then besides overwriting any .words file,
 * it loads a lesson with the new dictionary.
 */
void
velo_text_write_to_file (gchar * text_raw, gboolean overwrite)
{
	gchar *dict_path;
	gchar *dictio_name;
	gchar *text_filtered;
	FILE *fh_destiny;
	dictio_name = g_strdup_printf ("(%s)", _("Pasted_or_dropped"));
	dict_path = g_strconcat (main_path_user (), G_DIR_SEPARATOR_S, dictio_name, ".words", NULL);
	assert_user_dir ();
	if (!(fh_destiny = (FILE *) g_fopen (dict_path, "w")))
	{
		gdk_beep ();
		g_warning ("couldn't create the file:\n <%s>", dict_path);
		if (overwrite == FALSE)
		{
			g_free (dict_path);
			g_free (dictio_name);
			return;
		}
	}
	g_free (dict_path);
	/* Filter the text
	 */
	text_filtered = velo_filter_utf8 (text_raw);
	fwrite (text_filtered, sizeof (gchar), strlen (text_filtered), fh_destiny);
	fclose (fh_destiny);
	g_free (text_filtered);
	if (overwrite == TRUE)
	{
		velo_init_dict (dictio_name);
		tutor_set_query (QUERY_INTRO);
		tutor_process_touch ('\0');
	}
	g_free (dictio_name);
}
/**********************************************************************
 * Reads the text file "file_name" and write to the dictionary.
 * If overwrite is TRUE, then besides overwriting any .words file,
 * it loads a lesson with the new dictionary.
 */
void
velo_create_dict (gchar * file_name, gboolean overwrite)
{
	gchar *dict_path;
	gchar *dictio_name;
	gchar *text_raw;
	gchar *text_filtered;
	FILE *fh_destiny;
	if (!file_name)
	{
		gdk_beep ();
		g_warning ("velo_create_dict(): null file name as first argument.");
		return;
	}
	if (!g_file_get_contents (file_name, &text_raw, NULL, NULL))
	{
		gdk_beep ();
		g_warning ("couldn't read the file:\n <%s>", file_name);
		return;
	}
	dictio_name = g_path_get_basename (file_name);
	dict_path = g_strconcat (main_path_user (), G_DIR_SEPARATOR_S, dictio_name, ".words", NULL);
	assert_user_dir ();
	if (!(fh_destiny = (FILE *) g_fopen (dict_path, "w")))
	{
		gdk_beep ();
		g_warning ("couldn't create the file:\n <%s>", dict_path);
		if (overwrite == FALSE)
		{
			g_free (dict_path);
			g_free (dictio_name);
			return;
		}
	}
	g_free (dict_path);
	/* Filter the text
	 */
	text_filtered = velo_filter_utf8 (text_raw);
	fwrite (text_filtered, sizeof (gchar), strlen (text_filtered), fh_destiny);
	fclose (fh_destiny);
	g_free (text_raw);
	g_free (text_filtered);
	if (overwrite == TRUE)
	{
		velo_init_dict (dictio_name);
		tutor_set_query (QUERY_INTRO);
		tutor_process_touch ('\0');
	}
	g_free (dictio_name);
}
/**********************************************************************
 * Put on the screen the final comments
 */
void
velo_comment (gdouble accuracy, gdouble velocity)
{
	gchar *tmp_str;
	GtkWidget *wg;
	GtkTextBuffer *buf;
	/*
	 * Comments
	 */
	if (accuracy < tutor_goal_accuracy ())
	{
		/*
		tmp_str = g_strdup_printf (_(" Your accuracy rate is not good enough.\n"
				      " I only can rely on you if it is greater than %.0f%%.\n"
				      " Please calm down and try it again.\n"), tutor_goal_accuracy ());
		*/
		tmp_str = g_strdup (":-(\n");
	}
	else if (velocity < 10)
		tmp_str =
			g_strdup (_(" You are just beginning.\n"
				" Be patient, try it again every day, rest and don't worry so much:\n"
				" persistence and practice will improve your velocity.\n"));
	else if (velocity < 20)
		tmp_str = g_strdup (_(" Still away from the highway. You can make better...\n"
					" Try at least 20 WPM.\n"));
	else if (velocity < 30)
		tmp_str = g_strdup (_(" You are doing well, but need to go faster.\n"
				      " And don't forget the accuracy. Try to get 30 WPM.\n"));
	else if (velocity < 40)
		tmp_str =
			g_strdup (_(" Fine. Now you need to start running.\n"
						" Can you reach 40 WPM?\n"));
	else if (velocity < tutor_goal_speed ())
		tmp_str = g_strdup_printf (_(" Very good. You are almost there.\n "
					"Can you finally reach %.0f WPM?\n"),
					tutor_goal_speed ());
	else if (velocity < 60)
		tmp_str =
			g_strdup (_(" Excellent. For this course, that is enough.\n"
						" Try now the fluidness exercises, OK?\n"));
	else if (velocity < 70)
		tmp_str =
			g_strdup (_(" Fast! Are you training for a competition?\n"
						" So, try to get 70 WPM!\n"));
	else if (velocity < 80)
		tmp_str = g_strdup (_(" Top of \"qwerty\"."
				      " Now it's time to change to the Dvorak mode.\n"
				      " Are you afraid of reaching 80 WPM?\n"));
	else if (velocity < 90)
		tmp_str = g_strdup (_(" Dvorak mode dominated!\n Can you fly at 90 WPM?\n"));
	else
		tmp_str =
			g_strdup (_
				  (" Dvorak master!\n"
				   " I have no words to express my admiration!\n"));
	wg = get_wg ("text_tutor");
	buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (wg));
	gtk_text_buffer_insert_at_cursor (buf, tmp_str, strlen (tmp_str));
	g_free (tmp_str);
}