/*************************************************************************************************************
* This file contains FTP upload functions
* 2012/10 by Dlxko
* Version 4.0
**************************************************************************************************************/
#include "FTPUpload.h"

//For dialogs tmp
static char dialog_text[DIALOG_BUFFER_SIZE];

// Counting free array of waiting messages to respond
static char char_waiting_message[MSG_NUMB_SIZE+1];
static int waiting_message;

// For writing sending message
static gchar *message;
static GtkTextIter end_iter;
static GtkTextMark *endmark;
static GtkTextIter start_iter;
static int character_count;
static gint line_count;

// Buffer for created socket
static char sending_text[BUF_SIZE];
static int sending_text_len;
static char sending_text_len_char[LENGHT_SIZE+1];

// For saved buddy number
static int buddy_number;

// Path stores
static char local_file[FILE_PATH_SIZE];
static char file_name[FILE_NAME_SIZE];
static char remote_url[FILE_PATH_SIZE];
static char char_addres[FILE_PATH_SIZE];
static std::string adress;

// For searching file name
static int last;
static int len;

// Curl variables
static  CURL *curl;
static  CURLcode result;
static  curl_off_t file_size;

// File structures
static  FILE *souce_file;
static  struct stat file_info;

// Reading variables
static curl_off_t nread;
static size_t retcode;

// Threat variables
static GThread *thread;

// File select
static GtkWidget *file_selector_widget;
static GtkWidget *file_selector_data;
static const gchar *selected_filename;

// Reading file function
static size_t read_callback(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
	retcode = fread(ptr, size, nmemb, stream);
	nread = (curl_off_t)retcode;
	return retcode;
}

// Thread function
static gpointer func( gpointer data )
{
	// Get remote URL with file name
	if(strlen(file_name) > 0)
		sprintf_s(remote_url, FILE_PATH_SIZE, "ftp://warriorsoftheworld.tym.cz:2WotW2@warriorsoftheworld.tym.cz/%s", file_name);
	else
	{
		function_show_warning_ftp(LANG_THREAD_FILENAME_IS_WRONG, 1);
		return (NULL);
	}

	// If no file write error
	if( stat(local_file, &file_info) )
	{
		memset(dialog_text, 0, DIALOG_BUFFER_SIZE);
		sprintf(dialog_text, "%s '%s'", LANG_THREAD_XOPEN_FILE, local_file);
		function_show_warning_ftp(dialog_text, 1);
		return (NULL);
	}

	// Get file size
	file_size = (curl_off_t)file_info.st_size;

	// Open file in binary mode
	if(fopen_s(&souce_file, local_file, "rb") != NULL)
	{
		function_show_warning_ftp(LANG_XOPEN_FILE_FOR_READING_BINAY, 1);
		return (NULL);
	}

	// Init curl
	curl_global_init(CURL_GLOBAL_ALL);
	curl = curl_easy_init();

	// Check if initialized
	if(!curl)
	{
		function_show_warning_ftp(LANG_XINITIALIZE_CURL, 1);
		return (NULL);
	}

	// Use the read function
	curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
	// Enable uploading
	curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
	// Set destination
	curl_easy_setopt(curl,CURLOPT_URL, remote_url);
	// Specify which file to upload
	curl_easy_setopt(curl, CURLOPT_READDATA, souce_file);
	// Set size of uploaded file
	curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_size);
	// Permform script
	result = curl_easy_perform(curl);
	// Cleanup
	curl_easy_cleanup(curl);

	// If everything OK
	if (!result)
	{
		// Count lenght
		sending_text_len = LENGHT_SIZE + OPCODE_SIZE + MSG_NUMB_SIZE + FILE_NAME_SIZE + DATA_ONE_SIZE + FILE_PATH_SIZE;
		sprintf_s(sending_text_len_char, LENGHT_SIZE, "%d", sending_text_len);

		// Update text for server with "DX_OPCODE_FLT" and name datas
		memset(sending_text,0,BUF_SIZE);
		memcpy(sending_text, sending_text_len_char, LENGHT_SIZE);
		memcpy(&sending_text[LENGHT_SIZE], DX_OPCODE_FLT, OPCODE_SIZE);
		memcpy(&sending_text[LENGHT_SIZE+OPCODE_SIZE], buddy[buddy_number].nick_name, strlen(buddy[buddy_number].nick_name));
		memcpy(&sending_text[LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE], char_waiting_message, MSG_NUMB_SIZE);
		memcpy(&sending_text[LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE+MSG_NUMB_SIZE], file_name, strlen(file_name));
		memcpy(&sending_text[LENGHT_SIZE+OPCODE_SIZE+FILE_NAME_SIZE+DATA_ONE_SIZE+MSG_NUMB_SIZE], remote_url, FILE_PATH_SIZE);

		// Send socket and print ok sended image
		send( s, sending_text, sending_text_len, 0 );
	}
	// Write failed image
	else function_show_warning(LANG_CANT_UPLOAD_FILE);

	// Cleanup
	active_ftp_upload = false;
	fclose(souce_file);
	curl_global_cleanup();

	// Exit thread and return
	g_thread_exit( NULL );
	return ( NULL );
}

// Store file path function
void store_filename (GtkWidget *widget, gpointer user_data)
{
	// Alloc error
	static GError *error = NULL;

	// Get file path and save it
	file_selector_data = GTK_WIDGET (user_data);
	selected_filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_selector_data));
	if(strlen(selected_filename) < 1)
	{
		function_show_warning_ftp(LANG_XGET_DATA_FROM_SELECTION, 1);
		return;
	}

	// Check size of path else save
	if (strlen(selected_filename) > FILE_PATH_SIZE)
	{
		function_show_warning_ftp(LANG_FILE_PATH_IS_TOO_LONG, 1);
		return;
	}
	sprintf_s(local_file, FILE_PATH_SIZE, "%s", selected_filename);

	// Get file name
	adress = local_file;
	last = adress.rfind("\\");
	len = adress.size();
	strcpy_s(char_addres, 300, adress.c_str());
	function_midcopy(char_addres, file_name, last+1, len);
	if (strlen(file_name) < 1)
	{
		function_show_warning_ftp(LANG_XGET_FILENAME_FROM_PATH, 1);
		return;
	}

	// Get time and inset into string, create char, copy from string to char
	std::string time = function_get_std_time();
	gchar *timemsg = new char[time.size()+1];
	timemsg[time.size()]=0;
	memcpy(timemsg,time.c_str(),time.size());

	// Create message with time if its necessary
	if(buddy[buddy_number].who_sender == 0 || buddy[buddy_number].who_sender == 3)
	{
		// Print message of time
		message = g_strconcat ("\n",timemsg, " - ", my_name, NULL);
		gtk_text_buffer_get_end_iter (buddy[buddy_number].buffer, &end_iter);
		gtk_text_buffer_insert (buddy[buddy_number].buffer, &end_iter, message, -1);
		g_free (message);

		// Make it bold
		line_count = gtk_text_buffer_get_line_count (buddy[buddy_number].buffer);
		gtk_text_buffer_get_iter_at_line(buddy[buddy_number].buffer, &start_iter, line_count);
		gtk_text_buffer_get_end_iter (buddy[buddy_number].buffer, &end_iter);
		gtk_text_buffer_apply_tag_by_name (buddy[buddy_number].buffer, "bold", &start_iter, &end_iter);
	}

	// Print other datas
	message = g_strconcat ("\n", LANG_SENDING_FILE, file_name, " ", NULL);
	gtk_text_buffer_get_end_iter (buddy[buddy_number].buffer, &end_iter);
	gtk_text_buffer_insert (buddy[buddy_number].buffer, &end_iter, message, -1);
	g_free (message);

	// Set sender as me
	buddy[buddy_number].who_sender = true;

	// Add image of sending status
	gtk_text_buffer_get_end_iter(buddy[buddy_number].buffer, &end_iter);
	gtk_text_buffer_insert_pixbuf(buddy[buddy_number].buffer, &end_iter, px_sending);
	character_count = gtk_text_buffer_get_char_count(buddy[buddy_number].buffer);

	// Scroll to end
	gtk_text_buffer_get_end_iter (buddy[buddy_number].buffer, &end_iter);
	endmark = gtk_text_mark_new ("E3", 0);
	gtk_text_buffer_add_mark (buddy[buddy_number].buffer, endmark, &end_iter);
	gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (buddy[buddy_number].text_view), endmark, 0.0, FALSE, 0, 0);
	gtk_text_buffer_delete_mark (buddy[buddy_number].buffer, endmark);

	do // Just look for empty waiting message slot
	{
		if(messages[waiting_message].waiting == true)
			++waiting_message;
		else
			break;
	}
	while (waiting_message < MAX_MESSAGES);

	// If more then maximum messages waiting
	if (waiting_message == MAX_MESSAGES)
	{
		function_show_warning_ftp(LANG_REACHED_MAX_WAITING_MESSAGES, 1);
		return;
	}

	// Update message structure
	messages[waiting_message].chat = buddy_number;
	messages[waiting_message].waiting = true;
	messages[waiting_message].char_count = character_count;

	// Sprintf msg number
	sprintf_s(char_waiting_message, MSG_NUMB_SIZE, "%d", waiting_message);

	// Create thread
	thread = g_thread_create_full( func, NULL, 0, FALSE, TRUE, G_THREAD_PRIORITY_LOW, &error );
	if( ! thread )
	{
		memset(dialog_text, 0, DIALOG_BUFFER_SIZE);
		sprintf(dialog_text, "%s : %s", LANG_XCREATE_UPLOAD_THREAD, error->message);
		function_show_warning_ftp(dialog_text, 1);
		g_error_free(error);
		return;
	}
}

// GTK button click action
void signal_ftp_upload(GtkWidget *unused_button, gint input_buddy_number)
{
	// Activate upload
	if(active_ftp_upload == true)
	{
		function_show_warning(LANG_ONLY_ONE_FTP_UPLOAD_ALLOWED);
		return;
	}
	active_ftp_upload = true;

	// Store buddy number
	buddy_number = input_buddy_number;

	// Check buddy number
	if (buddy_number == (MAX_BUDDIES + 1))
	{
		function_show_warning_ftp(LANG_XGET_DATA_FOR_INIT_UPLOAD, 1);
		return;
	}

	// Create dialog of file selection
	file_selector_widget = gtk_file_selection_new (LANG_SELECT_FILE_FOR_UPLOAD);
	gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(file_selector_widget));
	g_signal_connect (GTK_FILE_SELECTION (file_selector_widget)->ok_button, "clicked", G_CALLBACK (store_filename), file_selector_widget);
	g_signal_connect_swapped (GTK_FILE_SELECTION (file_selector_widget)->ok_button, "clicked", G_CALLBACK (gtk_widget_destroy), file_selector_widget);
	g_signal_connect_swapped (GTK_FILE_SELECTION (file_selector_widget)->cancel_button, "clicked", G_CALLBACK (gtk_widget_destroy), file_selector_widget);
	gtk_widget_show (file_selector_widget);
}