/*
    QAD - Qt ADvanced

    Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef BLOCKITEMPIN_H
#define BLOCKITEMPIN_H

#include "alignedtextitem.h"
#include "blockbase.h"
#include "qad_blockview_export.h"

#include <QDebug>
#include <QGraphicsEllipseItem>
#include <QGraphicsObject>
#include <QGraphicsScene>
#include <QGraphicsSceneHoverEvent>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsView>
#include <QPropertyAnimation>
#include <QStack>
#include <pivaluetree.h>
#include <qmath.h>


class BlockItem;
class BlockBusItem;


class QAD_BLOCKVIEW_EXPORT BlockItemPin
	: public QGraphicsObject
	, public PropertyStorage {
	friend class BlockView;
	friend class BlockItem;
	friend QDataStream & operator<<(QDataStream & s, const BlockItemPin * p);
	friend QDataStream & operator>>(QDataStream & s, BlockItemPin *& p);
	Q_OBJECT
	Q_PROPERTY(double pinSize READ pinSize WRITE resizePin DESIGNABLE false SCRIPTABLE false)

public:
	BlockItemPin(Qt::Alignment a = Qt::AlignLeft, int bus_type = 0, const QString & text_ = QString(), QGraphicsObject * parent_ = 0);

	enum State {
		Disconnected,
		Connected,
		Hover,
		Drop,
		Accept,
		Reject
	};

	enum Direction {
		None        = 0x0,
		Input       = 0x1,
		Output      = 0x2,
		InputOutput = 0x3
	};

	enum {
		Type = UserType + 3
	};

	void setPen(const QPen & p);
	QPen pen() const;
	void setBrush(const QBrush & b);
	QBrush brush() const;

	int busType() const { return bus_type; }
	Qt::Alignment alignment() const { return align; }
	QString text() const;
	State state() const { return state_; }

	void setBusType(int type_);
	void setAlignment(Qt::Alignment a);
	void setText(const QString & t);
	void setState(State s);

	void saveState();
	bool restoreState();
	void clearStateStack();

	void enlargePin(bool enlarge);

	PIValueTree & values() { return value_tree; }

	BlockItem * parent() const { return parent_; }
	QList<BlockBusItem *> connectedBuses() const { return buses_; }

public slots:
	void animAccept();

protected:
	void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override {}
	QRectF boundingRect() const override;
	int type() const override { return Type; }
	QVariant itemChange(GraphicsItemChange change, const QVariant & value) override;
	void hoverEnterEvent(QGraphicsSceneHoverEvent * e) override;
	void hoverLeaveEvent(QGraphicsSceneHoverEvent * e) override;
	void _init(bool affect_parent = false);
	void _reparent();
	QGraphicsView * _view() const;

	int bus_type;
	State state_;
	QGraphicsEllipseItem ell_item;
	QGraphicsSimpleTextItem text_item;
	QStack<State> sstate_;
	QList<BlockBusItem *> buses_;
	BlockItem * parent_;
	Qt::Alignment align;
	QBrush br[6];
	PIValueTree value_tree;

private slots:
	void animationAccept();

private:
	void resizePin(double r);
	double pinSize() const;

	QPropertyAnimation anim_pin_size;
	QPropertyAnimation anim_accept;
};


#endif // BLOCKITEMPIN_H
