#include "txstabwidget.h"
#include "latexeditorview.h"
#include "smallUsefulFunctions.h"

TxsTabWidget::TxsTabWidget(QWidget *parent) :
	QTabWidget(parent)
{
	setFocusPolicy(Qt::ClickFocus);
	setContextMenuPolicy(Qt::PreventContextMenu);

	ChangeAwareTabBar *tb = new ChangeAwareTabBar();
	tb->setContextMenuPolicy(Qt::CustomContextMenu);
	tb->setUsesScrollButtons(true);
	connect(tb, SIGNAL(customContextMenuRequested(QPoint)), this, SIGNAL(tabBarContextMenuRequested(QPoint)));
	connect(tb, SIGNAL(currentTabAboutToChange(int, int)), this, SLOT(currentTabAboutToChange(int, int)));
	connect(tb, SIGNAL(middleMouseButtonPressed(int)), this, SLOT(closeTab(int)));
	setTabBar(tb);

	if (hasAtLeastQt(4, 5)) {
		setDocumentMode(true);
		const QTabBar *tb = tabBar();
		connect(tb, SIGNAL(tabMoved(int, int)), this, SIGNAL(tabMoved(int, int)));
		connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
		setProperty("tabsClosable", true);
		setProperty("movable", true);
	}
	connect(this, SIGNAL(currentChanged(int)), this, SIGNAL(currentEditorChanged()));
}

void TxsTabWidget::moveTab(int from, int to)
{
	int cur = currentIndex();
	QString text = tabText(from);
	QWidget *wdg = widget(from);
	removeTab(from);
	insertTab(to, wdg, text);
	if (cur == from) setCurrentIndex(to);
	else if (from < to && cur >= from && cur < to)
		setCurrentIndex(cur - 1);
	else if (to > from && cur >= from && cur < to)
		setCurrentIndex(cur + 1);
}

QList<LatexEditorView *> TxsTabWidget::editors() const
{
	QList<LatexEditorView *> list;
	for (int i = 0; i < count(); i++) {
		LatexEditorView *edView = qobject_cast<LatexEditorView *>(widget(i));
		Q_ASSERT(edView); // there should only be editors as tabs
		list.append(edView);
	}
	return list;
}

bool TxsTabWidget::containsEditor(LatexEditorView *edView) const
{
	if (!edView) return false;
	return (indexOf(edView) >= 0);
}

LatexEditorView *TxsTabWidget::currentEditorView() const
{
	return qobject_cast<LatexEditorView *>(currentWidget());
}

void TxsTabWidget::setCurrentEditor(LatexEditorView *edView)
{
	if (currentWidget() == edView)
		return;

	if (indexOf(edView) < 0) {
		// catch calls in which editor is not a member tab.
		// TODO: such calls are deprecated as bad practice. We should avoid them in the long run. For the moment the fallback to do nothing is ok.
		qDebug() << "Warning (deprecated call): TxsTabWidget::setCurrentEditor: editor not member of TxsTabWidget";
#ifndef QT_NO_DEBUG
		txsWarning("Warning (deprecated call): TxsTabWidget::setCurrentEditor: editor not member of TxsTabWidget");
#endif
		return;
	}
	setCurrentWidget(edView);
}

void TxsTabWidget::gotoNextDocument()
{
	if (count() <= 1) return;
	int cPage = currentIndex() + 1;
	if (cPage >= count()) setCurrentIndex(0);
	else setCurrentIndex(cPage);
}

void TxsTabWidget::gotoPrevDocument()
{
	if (count() <= 1) return;
	int cPage = currentIndex() - 1;
	if (cPage < 0) setCurrentIndex(count() - 1);
	else setCurrentIndex(cPage);
}

void TxsTabWidget::currentTabAboutToChange(int from, int to)
{
	LatexEditorView *edFrom = qobject_cast<LatexEditorView *>(widget(from));
	LatexEditorView *edTo = qobject_cast<LatexEditorView *>(widget(to));
	REQUIRE(edFrom);
	REQUIRE(edTo);
	emit editorAboutToChangeByTabClick(edFrom, edTo);
}

void TxsTabWidget::closeTab(int i)
{
	int cur = currentIndex();
	int total = count();
	setCurrentIndex(i);
	emit closeCurrentEditorRequest();
	if (cur > i) cur--; //removing moves to left
	if (total != count() && cur != i) //if user clicks cancel stay in clicked editor
		setCurrentIndex(cur);
}

void TxsTabWidget::closeTab(LatexEditorView *edView)
{
	int i = indexOf(edView);
	if (i >= 0) closeTab(i);
}

void TxsTabWidget::removeEditor(LatexEditorView *edView)
{
	int i = indexOf(edView);
	if (i >= 0)
		removeTab(i);
}

void TxsTabWidget::insertEditor(LatexEditorView *edView, int pos, bool asCurrent)
{
	Q_ASSERT(edView);
	insertTab(pos, edView, "?bug?");
	if (asCurrent) setCurrentEditor(edView);
}

void ChangeAwareTabBar::mousePressEvent(QMouseEvent *event)
{
	if (event->button() == Qt::LeftButton) {
		int toIndex = tabAt(event->pos());
		if (toIndex >= 0) {
			emit currentTabAboutToChange(currentIndex(), toIndex);
		}
	}
#if QT_VERSION>=0x040700
	else if (event->button() == Qt::MiddleButton) {
		int tabNr = tabAt(event->pos());
		if (tabNr >= 0) {
			emit middleMouseButtonPressed(tabNr);
		}
	}
#endif
	QTabBar::mousePressEvent(event);
}
