#include <QPainter>
#include <QStyleOption>
#include <QApplication>
#include "button.h"


SHSButton::SHSButton(QWidget * parent): QToolButton(parent) {
	init();
}


SHSButton::SHSButton(int id__, const QString & text): QToolButton(0) {
	init();
	id_click = id_yes = id_no = id__;
	setText(text);
}


SHSButton::~SHSButton() {
}


void SHSButton::init() {
	pw = parentWidget();
	if (pw != 0) {
		while (pw->parentWidget() != 0)
			pw = pw->parentWidget();
		pw->installEventFilter(this);
		//qDebug() << "listen for activate" << pw;
	}
	setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
	setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
	//setIconSize(QSize(128, 128));
	connect(this, SIGNAL(clicked(bool)), this, SLOT(_clicked()));
	connect(this, SIGNAL(toggled(bool)), this, SLOT(_toggled(bool)));
	image_conn.load(":/icons/connected.png");
	image_disconn.load(":/icons/disconnected.png");
	image_invisible.load(":/icons/invisible.png");
	animation.setTargetObject(this);
	animation.setPropertyName("h__currentColor");
	animation.setEasingCurve(QEasingCurve::OutSine);
	animation.setDuration(350);
	anim_ = 300;
	rele_ = 1000;
	delay_blink = 500;
	bdebug_ = false;
	anim = auto_gray = _first = visible_ = true;
	state_ = Gray;
	id_click = id_yes = id_no = -1;
	timer = 0;
	dtimer = -1;
	pal = palette();
	col_yes = QColor(Qt::green);
	col_no = QColor(Qt::red);
	col_down = QColor(Qt::yellow);
	col_gray = col_cur = col_up = pal.button().color();
	col_dst = col_gray;
	setCurrentColor(col_dst);
}


void SHSButton::drawButton(QPainter & p) {
	QStyleOptionToolButton so;
	initStyleOption(&so);
	if (so.icon.isNull() || so.toolButtonStyle == Qt::ToolButtonTextOnly) {
		style()->drawComplexControl(QStyle::CC_ToolButton, &so, &p, this);
		if (!visible_ & bdebug_) p.drawImage(width() - 20, 4, image_invisible);
		return;
	}
	QString t = so.text;
	QIcon i = so.icon;
	so.text.clear();
	so.icon = QIcon();
	style()->drawComplexControl(QStyle::CC_ToolButton, &so, &p, this);
	QSize ts = t.isEmpty() ? QSize() : fontMetrics().size(0, t), ps = size() * 0.9 - QSize(4, 4);
	switch (so.toolButtonStyle) {
	case Qt::ToolButtonIconOnly: ts = QSize(); break;
	case Qt::ToolButtonTextBesideIcon: ps.rwidth() -= ts.width(); break;
	case Qt::ToolButtonTextUnderIcon: ps.rheight() -= ts.height(); break;
	default: break;
	}
	QSize is = i.actualSize(so.iconSize);
	if (ps.width() < is.width() || ps.height() < is.height())
		is.scale(ps, Qt::KeepAspectRatio);
	QIcon::Mode mode = QIcon::Normal;
	//ts.setHeight(ts.height() / 1.666);
	if (!so.state.testFlag(QStyle::State_Enabled))
		mode = QIcon::Disabled;
	else if (so.state.testFlag(QStyle::State_MouseOver))
		mode = QIcon::Active;
	if (t.isEmpty() || so.toolButtonStyle == Qt::ToolButtonIconOnly)
		p.drawPixmap((width() - is.width()) / 2, (height() - is.height()) / 2, i.pixmap(is, mode));
	else {
		if (so.toolButtonStyle == Qt::ToolButtonTextBesideIcon) {
			p.drawPixmap((width() - ts.width() - is.width()) / 2 - 4, (height() - is.height()) / 2, i.pixmap(is, mode));
			//p.drawText((width() - ts.width() + is.width()) / 2 + 2, (height() + ts.height()) / 2, t);
			int w = (width() - ts.width() + is.width()) / 2 + 4;
			p.drawText(QRectF(w, 0, ts.width(), height()), Qt::AlignCenter, t);
		} else {
			p.drawPixmap((width() - is.width()) / 2, (height() - is.height() - ts.height()) / 2 - 4, i.pixmap(is, mode));
			//p.drawText((width() - ts.width()) / 2, (height() + is.height() + ts.height()) / 2 + 2, t);
			int h = (height() + is.height() - ts.height()) / 2 + 4;
			p.drawText(QRectF(0, h, width(), height() - h), Qt::AlignTop | Qt::AlignHCenter, t);
		}
	}
	if (!visible_ & bdebug_) p.drawImage(width() - 20, 4, image_invisible);
}


QSize SHSButton::sizeHint() const {
	if (icon().isNull() || toolButtonStyle() == Qt::ToolButtonTextOnly)
		return QToolButton::sizeHint();
	return QToolButton::sizeHint() + (icon().actualSize(iconSize()) * 0.1);
}


QSize SHSButton::minimumSizeHint() const {
	return QToolButton::minimumSizeHint();
}


bool SHSButton::eventFilter(QObject * o, QEvent * e) {
	//qDebug() << e;
	if (e->type() == QEvent::User || e->type() == QEvent::Polish) {
		//if (!_first) return QObject::eventFilter(o, e);
		_first = false;
		//qDebug() << "activate" << e;
		if (autoConnect())
			o->removeEventFilter(this);
		//connect();
	}
	return QObject::eventFilter(o, e);
}


void SHSButton::timerEvent(QTimerEvent * e) {
	if (e->timerId() == timer) {
		killTimer(e->timerId());
		timer = 0;
		setCurrentColor(col_blink);
		animateColor(col_dst);
		return;
	}
	if (e->timerId() == dtimer) {
		checkConnected();
		return;
	}
	QToolButton::timerEvent(e);
}


bool SHSButton::autoConnect() {
	//qDebug() << "autoConnect" << pw;
	pw = parentWidget();
	if (pw != 0) {
		while (pw->parentWidget() != 0)
			pw = pw->parentWidget();
	}
	if (pw == 0) return false;
	return false;
}


void SHSButton::checkConnected() {
	if (!command().isEmpty()) {
		update();
	}
}


void SHSButton::paintEvent(QPaintEvent * e) {
	QPainter p(this);
	drawButton(p);
	if (bdebug_) {
		if (!command().isEmpty()) {
			QFont f(p.font());
			f.setPointSizeF(f.pointSizeF() * 0.75);
			p.setFont(f);
			p.drawImage(4, 4, image_conn);
			//p.drawText(24, 16, device_);
			int th = p.fontMetrics().height() * 0.666;
			p.drawText(24, 4 + 16 + (th - 16) / 2, command());
			return;
		}
	}
}


void SHSButton::mousePressEvent(QMouseEvent * e) {
	animateColor(col_down);
	QToolButton::mousePressEvent(e);
	emit pressedID(id_click);
}


void SHSButton::mouseReleaseEvent(QMouseEvent * e) {
	setCurrentColor(col_down);
	animateColor(col_dst, true);
	QToolButton::mouseReleaseEvent(e);
	emit releasedID(id_click);
}


void SHSButton::animateColor(const QColor & tc, bool release) {
	if (anim) {
		animation.stop();
		animation.setStartValue(currentColor());
		animation.setEndValue(tc);
		animation.setDuration(release ? rele_ : anim_);
		animation.start();
	} else {
		col_cur = tc;
		applyColor();
	}
}


void SHSButton::applyState(State s) {
	if (s == state_) return;
	State ps = state_;
	state_ = s;
	emit stateChanged(state_, ps);
	emit stateChangedID(id_click, state_, ps);
}


void SHSButton::blink(const QColor & tc) {
	col_blink = tc;
	if (timer > 0) killTimer(timer);
	timer = startTimer(delay_blink);
}


void SHSButton::parseCommand(QString all, QString * dev, QString * cmd, QVector<QVariant> * args) {
	int bi = all.indexOf('(');
	if (bi > 0) {
		QString bs = all.right(all.size() - bi).trimmed();
		all.resize(bi); all = all.trimmed();
		bs.remove(0, 1);
		bs.chop(1);
		if (args) {
			QStringList _al = bs.split(",");
			foreach (const QString & s, _al)
				*args << s;
		}
	}
	QStringList _sl = all.split(".");
	QString cd, cc;
	if (_sl.size() > 1) {
		if (dev) *dev = _sl[0];
		if (cmd) *cmd = _sl[1];
	}
}


void SHSButton::setState(State s) {
	switch (s) {
	case Gray: setStateGray(); break;
	case Yes: setStateYes(); break;
	case No: setStateNo(); break;
	default: break;
	};
}
