/*
 *	subtitleeditor -- a tool to create or edit subtitle
 *
 *	http://home.gna.org/subtitleeditor/
 *	https://gna.org/projects/subtitleeditor/
 *
 *	Copyright @ 2005-2009, kitone
 *
 *	This program is free software; you can redistribute it and/or modify
 *	it 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.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 

#include "utility.h"
#include <string>
#include <glibmm.h>
#include <iostream>
#include <sstream>
#include <gtkmm.h>
#include "cfg.h"
#include "subtitletime.h"
#include "subtitleeditorwindow.h"

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

/*
 *	profile name use by config dir
 */
Glib::ustring static_profile_name = "default";

/*
 *
 */
Glib::ustring build_message(const char *format, ...)
{
	Glib::ustring res;
	
	va_list args;
	char *formatted = NULL;

	va_start(args, format);
	formatted = g_strdup_vprintf(format, args);
	va_end(args);

	res = formatted;
	
	g_free(formatted);

	return res;
}

/*
 *	the profile name for the config dir
 *	~/config/subtitleeditor/{profile}
 */
void set_profile_name(const Glib::ustring &profile)
{
	se_debug_message(SE_DEBUG_UTILITY, "profile=%s", profile.c_str());

	if(!profile.empty())
		static_profile_name = profile;
}


/*
 *	~/.config/subtitleeditor/{profile}/
 *	XDG Base Directory Specification
 */
Glib::ustring get_config_dir(const Glib::ustring &file)
{
	const gchar *configdir = g_get_user_config_dir();
	
	Glib::ustring path = Glib::build_filename(configdir, "subtitleeditor");

	// create config path if need
	if(Glib::file_test(path, Glib::FILE_TEST_IS_DIR) == false)
	{
		//g_mkdir(path.c_str(), 0700);
		Glib::spawn_command_line_sync("mkdir " + path);
	}
	
	// create profile path if need
	path = Glib::build_filename(path, static_profile_name);

	if(Glib::file_test(path, Glib::FILE_TEST_IS_DIR) == false)
	{
		Glib::spawn_command_line_sync("mkdir " + path);
	}


	return Glib::build_filename(path, file);
}


/*
 *
 */
void dialog_warning(const Glib::ustring &primary_text, const Glib::ustring &secondary_text)
{
	Glib::ustring msg;

	msg += "<span weight=\"bold\" size=\"larger\">";
	msg += primary_text;
	msg += "</span>\n\n";
	msg += secondary_text;

	Gtk::MessageDialog dialog(msg, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true);
	dialog.run();
	//MessageDialog *dialog = new MessageDialog(msg, Gtk::MESSAGE_WARNING);
}

/*
 *
 */
void dialog_error(const Glib::ustring &primary_text, const Glib::ustring &secondary_text)
{
	Glib::ustring msg;

	msg += "<span weight=\"bold\" size=\"larger\">";
	msg += primary_text;
	msg += "</span>\n\n";
	msg += secondary_text;

	Gtk::MessageDialog dialog(msg, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
	dialog.run();
	//MessageDialog *dialog = new MessageDialog(msg, Gtk::MESSAGE_ERROR);
}


namespace utility
{
	bool string_to_bool(const std::string &str)
	{
		std::istringstream s(str);
		bool val = false;
		s >> val;
		return val;
	}
	
	/*
	 *
	 */
	int string_to_int(const std::string &str)
	{
		std::istringstream s(str);
		int val = 0;
		s >> val;
		return val;
	}

	/*
	 *
	 */
	int string_to_long(const std::string &str)
	{
		std::istringstream s(str);
		long val = 0;
		s >> val;
		return val;
	}

	/*
	 *
	 */
	double string_to_double(const std::string &str)
	{
		std::istringstream s(str);
		double val = 0;
		s >> val;
		return val;
	}
	
	/*
	 *
	 */
	void split(const std::string &str, const char &c, std::vector<std::string> &array, int max)
	{
		array.clear();

		std::istringstream iss(str);
		std::string word;

		if(max > 0)
		{
			int count = 1;
			while(std::getline(iss, word, (count < max) ? c : '\n'))
			{
				//std::cout << "word:" << word << std::endl;
				array.push_back(word);

				++count;
			}
		}
		else
		{
			while(std::getline(iss, word, c))
			{
				//std::cout << "word:" << word << std::endl;
				array.push_back(word);
			}
		}
	}

	void usplit(const Glib::ustring &str, const Glib::ustring::value_type &delimiter, std::vector<Glib::ustring> &container)
	{
		Glib::ustring::const_iterator it = str.begin(), end = str.end(), first;

		for(first = it; it != end; ++it)
		{
			if(delimiter == *it)
			{
				if(first != it) // || keep_blank)
				{
					// extract the current field from the string
					container.push_back(Glib::ustring(first, it));
					// skip the next delimiter
					first = it; ++first;
				}
				else
					++first;
			}
		}

		if(first != it) // || keep_blank
		{
			// extract the last field from the string
			container.push_back(Glib::ustring(first, it));
		}
	}

	/*
	 * Search and replace function. 
	 */
	void replace(Glib::ustring &text, const Glib::ustring &pattern, const Glib::ustring &replace_by)
	{
		Glib::ustring::size_type pos = 0;
	
		while((pos = text.find(pattern, pos)) != Glib::ustring::npos)
		{
			text.replace(pos, pattern.size(), replace_by);
			pos = pos + replace_by.size();
		}
	}
	
	/*
	 * Search and replace function. 
	 */
	void replace(std::string &text, const std::string &pattern, const std::string &replace_by)
	{
		std::string::size_type pos = 0;
	
		while((pos = text.find(pattern, pos)) != std::string::npos)
		{
			text.replace(pos, pattern.size(), replace_by);
			pos = pos + replace_by.size();
		}
	}

	/*
	 *	transforme test/file.srt en /home/toto/test/file.srt 
	 */
	Glib::ustring create_full_path(const Glib::ustring &_path)
	{
		if(_path.empty())
			return Glib::ustring();

		if(Glib::path_is_absolute(_path))
			return _path;

		Glib::ustring path =_path;

		// remove ./
		{
			Glib::ustring str("./");
			if(path.compare(0, str.length(), str) == 0)
				path.replace(0, str.length(), "");
		}

		Glib::ustring curdir = Glib::get_current_dir();

		Glib::ustring newpath = Glib::build_filename(curdir, path);

		return newpath;
	}

	/*
	 * Get the number of characters per second.
	 * msec = SubtitleTime::totalmsecs
	 */
	double get_characters_per_second(const Glib::ustring &text, const long msecs)
	{
		if(msecs == 0)
			return 0;

		std::vector<int> num_characters = utility::get_characters_per_line(text);
		
		if (num_characters.size() == 0)
			return 0;

		unsigned int len = 0;

		for (std::vector<int>::const_iterator it = num_characters.begin(); it != num_characters.end(); ++it)
			len += *it;
		
		len += 2 * (num_characters.size() - 1);	// a newline counts as 2 characters

		if(len == 0)
			return 0;

		double cps = static_cast<double>(len * 1000) / msecs;

		return cps;
	}
	
	/*
	 *	get number of characters for each line in the text
	 */
	std::vector<int> get_characters_per_line(const Glib::ustring &text)
	{
		std::vector<int> num_characters;
		std::istringstream iss(utility::get_stripped_text(text));
		std::string line;

		while( std::getline(iss, line) )
		{
			Glib::ustring::size_type len = reinterpret_cast<Glib::ustring&>(line).size();
			num_characters.push_back(len);
		}
		
		return num_characters;
	}
	
	/*
	 * get a text stripped from tags
	 */
	Glib::ustring get_stripped_text(const Glib::ustring &text)
	{
		// pattern for tags like <i>, </i>, {\comment}, etc.
		static Glib::RefPtr<Glib::Regex> tag_pattern = Glib::Regex::create("<.*?>|{.*?}");

		return tag_pattern->replace(text, 0, "", static_cast<Glib::RegexMatchFlags>(0));
	}

	/*
	 *
	 */
	void set_transient_parent(Gtk::Window &window)
	{
		Gtk::Window *root = dynamic_cast<Gtk::Window*>(SubtitleEditorWindow::get_instance());
		if(root)
			window.set_transient_for(*root);
	}

}//namespace utility

