#include "tabwidget.h"
#include <qad_types.h>
#include <QApplication>
#include <QTabBar>
#include <QDebug>
#include <QMouseEvent>
#include <QStylePainter>
#include <QStyleOption>

template <typename T>
inline T qClamp(T v, T min, T max) {return qMin<T>(max, qMax<T>(min, v));}


SHSTabBar::SHSTabBar(QWidget * parent): QTabBar(parent) {
	setUsesScrollButtons(false);
	setExpanding(true);
	moveable_ = false;
	icon_left.load(":/icons/arrow-left.png");
	icon_right.load(":/icons/arrow-right.png");
	dx = pdx = 0;
}


void SHSTabBar::mousePressEvent(QMouseEvent * e) {
	if (!moveable_) {
		QTabBar::mousePressEvent(e);
		return;
	}
	if (e->buttons() > 0) pp = sp = e->pos();
	pdx = dx;
	dp = QPoint();
	//QTabBar::mousePressEvent(e);
}


void SHSTabBar::mouseMoveEvent(QMouseEvent * e) {
	if (!moveable_) {
		QTabBar::mouseMoveEvent(e);
		return;
	}
	if (e->buttons() > 0) {
		dx += (e->pos() - sp).x();
		dp += QPoint(qAbs<int>((e->pos() - pp).x()), qAbs<int>((e->pos() - pp).y()));
		pp = e->pos();
		//parentWidget()->update();
		emit needMoveBar();
	}
	QTabBar::mouseMoveEvent(e);
}


void SHSTabBar::mouseReleaseEvent(QMouseEvent * e) {
	if (!moveable_) {
		QTabBar::mouseReleaseEvent(e);
		return;
	}
	if (dp.manhattanLength() <= qApp->startDragDistance()
#ifdef ANDROID
		* 4
#else
		* 2
#endif
	)
		QTabBar::mousePressEvent(new QMouseEvent(QEvent::MouseButtonPress, e->pos(), e->button(), e->buttons(), e->modifiers()));
	QTabBar::mouseReleaseEvent(e);
}


void SHSTabBar::resizeEvent(QResizeEvent * e) {
	QTabBar::resizeEvent(e);
	emit needMoveBar();
}


void SHSTabBar::paintEvent(QPaintEvent * e) {
	QTabBar::paintEvent(e);
	QPainter p(this);
	p.setRenderHint(QPainter::SmoothPixmapTransform);
	int mdx = parentWidget()->width() - width(), iw = (height() - 10) / 1.8;
	if (dx < 0) {
		p.setOpacity(qMin<qreal>(1., -dx / 50.) / 1.666);
		p.drawImage(QRect(-dx, 5, iw, height() - 10), icon_left);
	}
	if (dx > mdx) {
		p.setOpacity(qMin<qreal>(1., (-mdx + dx) / 50.) / 1.666);
		p.drawImage(QRect(width() - dx + mdx - iw, 5, iw, height() - 10), icon_right);
	}
}



SHSTabWidget::SHSTabWidget(QWidget * parent): QTabWidget(parent) {
	m_autoSide = false;
	m_preferredVerticalSide = Top;
	m_preferredHorizontalSide = Left;
	id_emit = id_set = -1;
	bar = new SHSTabBar();
	prev_pos = tabPosition();
	connect(bar, SIGNAL(needMoveBar()), this, SLOT(moveBar()));
	setUsesScrollButtons(false);
	setTabBar(bar);
}


SHSTabWidget::~SHSTabWidget() {
}


void SHSTabWidget::resizeEvent(QResizeEvent * e) {
	QTabWidget::resizeEvent(e);
	moveBar();
	if (!isAutoSide() || (width() < 2) || (height() < 2)) return;
	int w = width(), h = height();
	if (tabPosition() == North || tabPosition() == South) {
		w -= tabBar()->height();
		h -= tabBar()->height();
		if (float(w) / h >= 1.2f) {
			if (m_preferredHorizontalSide == Left)  setTabPosition(West);
			if (m_preferredHorizontalSide == Right) setTabPosition(East);
		}
	} else {
		w -= tabBar()->width();
		h -= tabBar()->width();
		if (float(h) / w >= 1.2f) {
			if (m_preferredVerticalSide == Top)    setTabPosition(North);
			if (m_preferredVerticalSide == Bottom) setTabPosition(South);
		}
	}
}


void SHSTabWidget::paintEvent(QPaintEvent * e) {
	if (tabPosition() == North || tabPosition() == South) {
		QStylePainter p(this);
		QStyleOptionTabWidgetFrame opt;
		initStyleOption(&opt);
		opt.rect = style()->subElementRect(QStyle::SE_TabWidgetTabPane, &opt, this);
		opt.tabBarSize.setWidth(width());
		p.drawPrimitive(QStyle::PE_FrameTabWidget, opt);
	} else
		QTabWidget::paintEvent(e);
}


void SHSTabWidget::moveBar() {
	if (tabPosition() == North || tabPosition() == South) {
		bar->resize(qMax<int>(width(), bar->sizeHint().width()), bar->height());
		bar->dx = qClamp<int>(bar->dx, width() - bar->width(), 0);
		bar->moveable_ = width() < bar->width();
		bar->move(bar->dx, bar->y());
	}
	//else
	//	bar->move(bar->x(), bar->y());
}


void SHSTabWidget::setTabVisible(int index, bool visible) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
	QTabWidget::setTabVisible(index, visible);
#endif
	if (visible) m_hiddenTabs.removeAll(index);
	else if (!m_hiddenTabs.contains(index)) m_hiddenTabs << index;
}


QByteArray SHSTabWidget::__hiddenTabs__() const {
	return qSerialize(m_hiddenTabs);
}


void SHSTabWidget::__setHiddenTabs__(const QByteArray & ht) {
	m_hiddenTabs = qDeserialize<QVector<int>>(ht);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
	for (int i = 0; i < count(); ++i)
		QTabWidget::setTabVisible(i, !m_hiddenTabs.contains(i));
#endif
}
