#include "qad_locations.h"

#include <QApplication>
#include <QDebug>
#include <QDir>
#include <QDirIterator>
#include <QLibraryInfo>
#include <QTranslator>
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
#  include <QStandardPaths>
#else
#  include <QDesktopServices>
#endif

#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
#  define MOBILE_VIEW
#endif

QString QAD::loadedLanguage;


class __QADTranslators__ {
public:
	static QList<QTranslator *> & translators() {
		static QList<QTranslator *> ret;
		return ret;
	}

private:
};


QString QAD::userPath(QAD::LocationType loc, QString name) {
	QString dir, ext;
	switch (loc) {
	case ltConfig: ext = ".conf"; break;
	case ltCache: ext = ".cache"; break;
	}
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
	QStandardPaths::StandardLocation l = QStandardPaths::AppConfigLocation;
	switch (loc) {
	case ltConfig: l = QStandardPaths::AppConfigLocation; break;
	case ltCache: l = QStandardPaths::CacheLocation; break;
	}
	dir = QStandardPaths::writableLocation(l);
#else
	QDesktopServices::StandardLocation l = QDesktopServices::DataLocation;
	switch (loc) {
	case ltConfig: l = QDesktopServices::DataLocation; break;
	case ltCache: l = QDesktopServices::CacheLocation; break;
	}
	dir = QDesktopServices::storageLocation(l);
#endif
	if (!QDir(dir).exists()) QDir().mkpath(dir);
	return dir + "/" + name + ext;
}


QStringList QAD::resourcePaths(QString type) {
	QStringList ret;
	ret << (QApplication::applicationDirPath() + "/" + type);
#ifdef MOBILE_VIEW
	ret << (":/" + type);
#elif defined(Q_OS_MACOS)
	ret << (QApplication::applicationDirPath() + "/../Resources/" + type);
#elif defined(Q_OS_WINDOWS)
#else
	ret << QString("/usr/share/%1/%2/%3").arg(QApplication::organizationName(), QApplication::applicationName(), type);
	ret << QString("/usr/share/%1/%2").arg(QApplication::organizationName(), type);
#endif
	return ret;
}


void QAD::loadTranslations(QString lang) {
	unloadTranslations();
	if (lang.isEmpty()) lang = QLocale().bcp47Name();
	QString short_lang = lang.left(2);
	loadedLanguage     = short_lang;
	QStringList dirs   = resourcePaths("lang");
	QString std_dir    = QDir::cleanPath(QLibraryInfo::location(QLibraryInfo::TranslationsPath));
	bool has_std       = false;
	for (const QString & d: dirs) {
		if (QDir::cleanPath(d) == std_dir) {
			has_std = true;
			break;
		}
	}
	if (!has_std) dirs << std_dir;
	for (const QString & d: dirs) {
		QDirIterator dit(d);
		while (dit.hasNext()) {
			dit.next();
			if (!dit.filePath().endsWith(".qm")) continue;
			if (!dit.fileInfo().baseName().endsWith(lang) && !dit.fileInfo().baseName().endsWith(short_lang)) continue;
			if (dit.fileName() == QString("qt_%1.qm").arg(short_lang)) continue;
			QTranslator * tr = new QTranslator();
			if (tr->load(dit.filePath())) {
				qApp->installTranslator(tr);
				__QADTranslators__::translators() << tr;
				// qDebug() << "Add tr" << dit.fileName();
			} else {
				qDebug() << "Can`t load translation" << dit.fileName();
				delete tr;
			}
		}
	}
}


void QAD::unloadTranslations() {
	// qDebug() << "removeTranslator ...";
	for (QTranslator * t: __QADTranslators__::translators()) {
		qApp->removeTranslator(t);
		delete t;
	}
	__QADTranslators__::translators().clear();
	// qDebug() << "removeTranslator done";
}


QStringList QAD::availableTranslations() {
	QSet<QString> ret;
	QStringList dirs = resourcePaths("lang");
	for (const QString & d: dirs) {
		QDirIterator dit(d);
		while (dit.hasNext()) {
			dit.next();
			if (!dit.filePath().endsWith(".qm")) continue;
			QTranslator * tr = new QTranslator();
			if (tr->load(dit.filePath())) {
				QString fn = dit.fileInfo().baseName(), lang[2];
				if (fn.contains("_")) {
					lang[0] = fn.right(fn.size() - fn.lastIndexOf("_") - 1);
					fn.chop(lang[0].size() + 1);
					if (fn.contains("_")) {
						lang[1] = fn.right(fn.size() - fn.lastIndexOf("_") - 1);
						fn.chop(lang[1].size() + 1);
						lang[1].append("_" + lang[0]);
					}
				}
				for (int i = 0; i < 2; ++i) {
					QLocale loc(lang[i]);
					if (loc.language() != QLocale::C) ret << lang[i];
				}
			}
			delete tr;
		}
	}
	return ret.values();
}
