/**
 * \file qt_helpers.C
 * This file is part of LyX, the document processor.
 * Licence details can be found in the file COPYING.
 *
 * \author Dekel Tsur
 * \author Jürgen Spitzmüller
 *
 * Full author contact details are available in file CREDITS.
 */

#include <config.h>

#include "lengthcombo.h"
#include "qt_helpers.h"

#include "lengthcommon.h"
#include "gettext.h"

#include "support/lstrings.h"
#include "support/convert.h"

#include <qcombobox.h>
#include <qlineedit.h>
#include <qtextcodec.h>

#include <algorithm>

#ifdef I18N
#include <iostream.h>
#include "support/types.h"
#include "lyxcodeconv.h"
extern LyXCodeConv codeconverter;
#endif

using lyx::support::isStrDbl;

using std::make_pair;
using std::string;
using std::pair;


string makeFontName(string const & family, string const & foundry)
{
	if (foundry.empty())
		return family;
#if QT_VERSION  >= 300
	return family + " [" + foundry + ']';
#else
	return foundry + '-' + family;
#endif
}


pair<string,string> parseFontName(string const & name)
{
#if QT_VERSION  >= 300
	string::size_type const idx = name.find('[');
	if (idx == string::npos || idx == 0)
		return make_pair(name, string());
	return make_pair(name.substr(0, idx - 1),
			 name.substr(idx + 1, name.size() - idx - 2));
#else
	string::size_type const idx = name.find('-');
	if (idx == string::npos || idx == 0)
		return make_pair(name, string());
	return make_pair(name.substr(idx + 1),
			 name.substr(0, idx));
#endif
}


string widgetsToLength(QLineEdit const * input, LengthCombo const * combo)
{
	QString length = input->text();
	if (length.isEmpty())
		return string();

	// don't return unit-from-choice if the input(field) contains a unit
	if (isValidGlueLength(fromqstr(length)))
		return fromqstr(length);

	LyXLength::UNIT unit = combo->currentLengthItem();

	return LyXLength(length.toDouble(), unit).asString();
}


LyXLength widgetsToLength(QLineEdit const * input, QComboBox const * combo)
{
	QString length = input->text();
	if (length.isEmpty())
		return LyXLength();

	// don't return unit-from-choice if the input(field) contains a unit
	if (isValidGlueLength(fromqstr(length)))
		return LyXLength(fromqstr(length));

	LyXLength::UNIT unit = unitFromString(fromqstr(combo->currentText()));

	return LyXLength(length.toDouble(), unit);
}


void lengthToWidgets(QLineEdit * input, LengthCombo * combo,
	string const & len, LyXLength::UNIT defaultUnit)
{
	if (len.empty()) {
		// no length (UNIT_NONE)
		combo->setCurrentItem(defaultUnit);
		input->setText("");
	} else if (!isValidLength(len) && !isStrDbl(len)) {
		// use input field only for gluelengths
		combo->setCurrentItem(defaultUnit);
		input->setText(toqstr(len));
	} else {
		combo->setCurrentItem(LyXLength(len).unit());
		input->setText(toqstr(convert<string>(LyXLength(len).value())));
	}
}


QString const toqstr(char const * str)
{
#ifdef I18N
QTextCodec * codec = QTextCodec::codecForLocale();
return codec->toUnicode(str);
#else
	return QString::fromAscii(str);
#endif
}

#ifdef I18N
QString const wtoqstr(lyx::char_type const * str)
{
        QTextCodec * codec = QTextCodec::codecForLocale();
        size_t len =  codeconverter.lyxwclen(str);
        char * mbs = new char [len * 2 + 1];
        codeconverter.lyxwcstombs(mbs, str, len * 2 + 1); 
        return codec->toUnicode(mbs); 
}
#endif


QString const toqstr(string const & str)
{
	return toqstr(str.c_str());
}


QString const qt_(char const * str)
{
	return toqstr(_(str));
}


QString const qt_(string const & str)
{
	return toqstr(_(str));
}


string const fromqstr(QString const & str)
{
	//return str;
#ifdef I18N
        QTextCodec const * const codec = QTextCodec::codecForLocale();
        QCString const tmpstr = codec->fromUnicode(str);
        return tmpstr.isEmpty() ? string() : string(tmpstr);
#else
	return str.ascii() ? str.ascii() : "";
#endif
}


string const formatted(string const & text, int w)
{
	string sout;

	if (text.empty())
		return sout;

	string::size_type curpos = 0;
	string line;

	for (;;) {
		string::size_type const nxtpos1 = text.find(' ',  curpos);
		string::size_type const nxtpos2 = text.find('\n', curpos);
		string::size_type const nxtpos = std::min(nxtpos1, nxtpos2);

		string const word = nxtpos == string::npos ?
			text.substr(curpos) : text.substr(curpos, nxtpos-curpos);

		bool const newline = (nxtpos2 != string::npos &&
				      nxtpos2 < nxtpos1);

		string const line_plus_word =
			line.empty() ? word : line + ' ' + word;

		// FIXME: make w be size_t
		if (int(line_plus_word.length()) >= w) {
			sout += line + '\n';
			if (newline) {
				sout += word + '\n';
				line.erase();
			} else {
				line = word;
			}

		} else if (newline) {
			sout += line_plus_word + '\n';
			line.erase();

		} else {
			if (!line.empty())
				line += ' ';
			line += word;
		}

		if (nxtpos == string::npos) {
			if (!line.empty())
				sout += line;
			break;
		}

		curpos = nxtpos + 1;
	}

	return sout;
}
