#include <QMessageBox>
#include <QFileDialog>
#include <QInputDialog>
#include <QFontDialog>
#include <QScrollBar>
#include <QTimer>
#include "project_tree.h"

const char qt_new_form[] =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
<ui version=\"4.0\">\
 <class>%1</class>\
 <widget class=\"QWidget\" name=\"%2\">\
  <property name=\"geometry\">\
   <rect>\
	<x>0</x>\
	<y>0</y>\
	<width>400</width>\
	<height>300</height>\
   </rect>\
  </property>\
  <property name=\"windowTitle\">\
   <string>%3</string>\
  </property>\
 </widget>\
 <resources/>\
 <connections/>\
</ui>";

enum ProjectItemType {
	pit_ui = 1,
	pit_dat,
	pit_var,
	pit_cm,
	pit_qs,
	pit_res_root,
	pit_res,
	pit_count,
};



ProjectTree::ProjectTree(QWidget * parent): QWidget(parent), Ui::ProjectTree() {
	setupUi(this);
	icon_ui   = QIcon(":/icons/designer-qt5.png");
	icon_dat  = QIcon(":/icons/database.png");
	icon_var  = QIcon(":/icons/code-var.png");
	icon_cm   = QIcon(":/icons/piconnection.png");
	icon_qs   = QIcon(":/icons/code-union.png");
	icon_res  = QIcon(":/icons/utilities-file-archiver.png");
	icon_file = QIcon(":/icons/application-x-object.png");
	icon_dir  = QIcon(":/icons/document-open.png");
	treeProject->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
	treeProject->addActions(QList<QAction*>() << actionAssign_file << actionNew_form << actionAdd_files << actionAdd_directory
							<< actionRemove_from_project << actionSet_as_main << actionEdit_form << actionIncludeScript);
	treeProject->viewport()->installEventFilter(this);
	connect(CORE, SIGNAL(projectChanged()), this, SLOT(projectChanged()));
	emit CORE->projectChanged();
}


ProjectTree::~ProjectTree() {
}


bool ProjectTree::eventFilter(QObject * o, QEvent * e) {
	//qDebug() << o << e;
	if (o == treeProject->viewport()) {
		if (e->type() == QEvent::ContextMenu) {
			QTreeWidgetItem * ti = treeProject->currentItem();
			bool aen[5] = {false, false, false, false, false};
			QString fp;
			int tit = 0;
			if (ti) {
				tit = ti->data(0, Qt::UserRole).toInt();
				if (tit > 0 && tit < pit_count) {
					aen[0] = (tit == pit_qs || tit == pit_res);
					aen[1] = (tit != pit_qs && tit != pit_res);
				}
				aen[2] = tit == pit_ui;
				fp = ti->text(1);
				aen[3] = aen[0] && (fp != RUNTIME->server_project.qs_main) && (tit != pit_res);
				aen[4] = tit == pit_res_root;
			}
			actionRemove_from_project->setVisible(aen[0]);
			actionSet_as_main->setVisible(aen[3]);
			actionIncludeScript->setVisible(aen[3]);
			actionAssign_file->setVisible(aen[1] && (tit != pit_res_root));
			actionNew_form->setVisible(aen[2]);
			actionEdit_form->setVisible(aen[2] && !fp.isEmpty());
			actionAdd_files->setVisible(aen[4]);
			actionAdd_directory->setVisible(aen[4]);
		}
		return QWidget::eventFilter(o, e);
	}
	return QWidget::eventFilter(o, e);
}


void ProjectTree::on_actionAdd_files_triggered() {
	QStringList fl = QFileDialog::getOpenFileNames(this, "Select files", "");
	if (fl.isEmpty()) return;
	QApplication::setOverrideCursor(Qt::WaitCursor);
	QDir cd;
	foreach (QString f, fl) {
		QString ln = QFileInfo(f).fileName();
		QString nn = cd.absolutePath() + "/res/" + ln;
		QFile::remove(nn);
		QFile::copy(f, nn);
		if (!RUNTIME->server_project.res.contains(ln))
			RUNTIME->server_project.res << ln;
	}
	QApplication::setOverrideCursor(Qt::ArrowCursor);
	emit CORE->projectChanged();
}


void ProjectTree::on_actionAdd_directory_triggered() {
	QString d = QFileDialog::getExistingDirectory(this, "Select directory", "");
	if (d.isEmpty()) return;
	QApplication::setOverrideCursor(Qt::WaitCursor);
	QString ln = QFileInfo(d).fileName();
	QString nn = QDir().absolutePath() + "/res/" + ln;
	if (!copyDir(d, nn)) {
		QApplication::setOverrideCursor(Qt::ArrowCursor);
		QMessageBox::critical(this, "Server designer", tr("Can`t copy \"%1\"!").arg(d));
		return;
	}
	ln += '/';
	if (!RUNTIME->server_project.res.contains(ln))
		RUNTIME->server_project.res << ln;
	QApplication::setOverrideCursor(Qt::ArrowCursor);
	emit CORE->projectChanged();
}


void ProjectTree::on_actionRemove_from_project_triggered() {
	QTreeWidgetItem * i = treeProject->currentItem();
	if (!i) return;
	if (i->data(0, Qt::UserRole).toInt() == pit_qs) {
		RUNTIME->server_project.removeScriptFile(i->text(1));
	}
	if (i->data(0, Qt::UserRole).toInt() == pit_res) {
		RUNTIME->server_project.res.removeAll(i->text(1));
	}
	emit CORE->projectChanged();
}


void ProjectTree::on_actionAssign_file_triggered() {
	QTreeWidgetItem * i = treeProject->currentItem();
	if (!i) return;
	QString tn;
	switch (i->data(0, Qt::UserRole).toInt()) {
	case pit_ui : tn = "Qt UI(*.ui)"; break;
	case pit_dat: tn = "Database files(*.dat)"; break;
	case pit_var: tn = "Variables file(*.var)"; break;
	case pit_cm : tn = "Connection files(*.cm)"; break;
	default: break;
	}
	if (tn.isEmpty()) return;
	QString f = QFileDialog::getOpenFileName(this, "Select file", i->text(1), tn);
	if (f.isEmpty()) return;
	emit CORE->loadFile(f);
}


void ProjectTree::on_actionNew_form_triggered() {
	QTreeWidgetItem * i = treeProject->currentItem();
	if (!i) return;
	QString p = QFileDialog::getSaveFileName(this, "Select file", i->text(1), "Qt UI(*.ui)");
	if (p.isEmpty()) return;
	if (!p.endsWith(".ui"))
		p += ".ui";
	QFile f(p);
	if (!f.exists()) {
		QString fname = toCName(QFileInfo(f).baseName());
		f.open(QIODevice::ReadWrite);
		f.write(QString(qt_new_form).arg(fname, fname, fname).toLatin1());
		f.close();
		QTimer::singleShot(0, this, SLOT(on_actionEdit_with_Qt_Designer_triggered()));
	}
	emit CORE->loadFile(p);
}


void ProjectTree::on_actionSet_as_main_triggered() {
	QTreeWidgetItem * i = treeProject->currentItem();
	if (!i) return;
	if (i->data(0, Qt::UserRole).toInt() != pit_qs) return;
	RUNTIME->server_project.qs_main = i->text(1);
	emit CORE->projectChanged();
}


void ProjectTree::on_actionIncludeScript_triggered() {
	QTreeWidgetItem * i = treeProject->currentItem();
	if (!i) return;
	if (i->data(0, Qt::UserRole).toInt() != pit_qs) return;
	QString inc = QString("include(\"%1\")").arg(i->text(1));
	CORE->widgetScripts->insertInclude(inc);
}


void ProjectTree::on_actionEdit_form_triggered() {
	if (RUNTIME->server_project.ui.isEmpty()) return;
	QStringList args;
	args << RUNTIME->server_project.ui;
	//if (!db_path.isEmpty()) args << ("-db=" + db_path);
	QString cwd = QFileInfo(RUNTIME->server_project.ui).absoluteDir().path();
	QFile cmdf(cwd + "/_ui_config_");
	if (cmdf.open(QIODevice::ReadWrite)) {
		cmdf.resize(0);
		QTextStream ts(&cmdf);
		ts << "dat = " << RUNTIME->server_project.dat.toUtf8() << "\n";
		ts << "var = " << RUNTIME->server_project.var.toUtf8() << "\n";
		cmdf.close();
	}
	QProcess::startDetached("designer", args, cwd);
}


void ProjectTree::on_treeProject_itemDoubleClicked(QTreeWidgetItem * item, int col) {
	if (item->data(0, Qt::UserRole).toInt() != pit_qs)
		return;
	emit CORE->loadScript(item->text(1));
}


#define ADD(n) \
	ti = new QTreeWidgetItem(QStringList() << #n << RUNTIME->server_project.n); \
	ti->setIcon(0, icon_##n); \
	ti->setData(0, Qt::UserRole, pit_##n); \
	treeProject->addTopLevelItem(ti)

void ProjectTree::projectChanged() {
	int vpos = treeProject->verticalScrollBar()->value();
	treeProject->clear();
	QTreeWidgetItem * ti;
	ADD(ui);  ti->setText(0, "Form");
	ADD(dat); ti->setText(0, "Database");
	ADD(var); ti->setText(0, "Variables");
	ADD(cm);  ti->setText(0, "Connection");
	ti = new QTreeWidgetItem(QStringList() << "Scripts");
	ti->setIcon(0, icon_qs);
	foreach (QString s, RUNTIME->server_project.qs) {
		QFileInfo fi(s);
		QTreeWidgetItem * si = new QTreeWidgetItem(QStringList() << fi.baseName() << s);
		si->setIcon(0, (fi.completeSuffix() == "qs" || fi.completeSuffix() == "js") ? icon_qs : icon_file);
		si->setData(0, Qt::UserRole, int(pit_qs));
		QFont f = si->font(0);
		f.setItalic(s == RUNTIME->server_project.qs_main);
		si->setFont(0, f);
		si->setFont(1, f);
		ti->addChild(si);
	}
	treeProject->addTopLevelItem(ti);
	ti->setExpanded(true);
	ti = new QTreeWidgetItem(QStringList() << "Resources");
	ti->setData(0, Qt::UserRole, pit_res_root);
	ti->setIcon(0, icon_res);
	foreach (QString s, RUNTIME->server_project.res) {
		QTreeWidgetItem * si = new QTreeWidgetItem(QStringList() << QFileInfo(s).baseName() << s);
		si->setIcon(0, s.endsWith("/") ? icon_dir : icon_file);
		si->setData(0, Qt::UserRole, int(pit_res));
		ti->addChild(si);
	}
	treeProject->addTopLevelItem(ti);
	ti->setExpanded(true);
	treeProject->verticalScrollBar()->setValue(vpos);
	emit CORE->saveProject();
}

#undef ADD


void ProjectTree::setCurrentFile(const QString & path) {
	QList<QTreeWidgetItem * > il = treeProject->findItems(QString(), Qt::MatchContains | Qt::MatchRecursive);
	foreach (QTreeWidgetItem * i, il) {
		if (i->data(0, Qt::UserRole).toInt() != pit_qs)
			continue;
		QFont f = i->font(0);
		f.setBold(i->text(1) == path);
		i->setFont(0, f);
	}
}
