/***************************************************************************
 *   Copyright (C) 2003-2005 by David Saxton                               *
 *   david@bluehaze.org                                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/

#ifndef ECNODE_H
#define ECNODE_H

#include "node.h"

// #include <q3valuevector.h>

class ECNode;
class Element;
class Pin;
class Switch;
class QTimer;

typedef QList<ECNode*> ECNodeList;
typedef QList<Element*> ElementList;
typedef QVector<Pin*> PinVector;

/**
@short Electrical node with voltage / current / etc properties
@author David Saxton
*/
class ECNode : public Node
{
	Q_OBJECT
	public:
		ECNode( ICNDocument *icnDocument, Node::node_type type, int dir, const QPoint &pos, QString *id = nullptr );
		~ECNode() override;

		void setParentItem( CNItem *parentItem ) override;
		
		/**
		 *  draws the ECNode; still only a pure virtual function
		 */
		void drawShape( QPainter &p ) override = 0;
		/**
		 * Set the number of pins "contained" in this node.
		 */
		void setNumPins( unsigned num );
		/**
		 * @return the number of pins in this node.
		 * @see setNumPins
		 */
		unsigned numPins() const { return m_pins.size(); }
		/**
		 * @return the pins in the node, as a vector
		 */
		PinVector pins() const { return m_pins; }

		/**
		 * @param num number of the
		 * @return pointer to a pin in this node, given by num
		 */
		Pin *pin( unsigned num = 0 ) const ;
			//{ return (num < m_pins.size()) ? m_pins[num] : nullptr; }

		bool showVoltageBars() const { return m_bShowVoltageBars; }
		void setShowVoltageBars( bool show ) { m_bShowVoltageBars = show; }
		bool showVoltageColor() const { return m_bShowVoltageColor; }
		void setShowVoltageColor( bool show ) { m_bShowVoltageColor = show; }
		void setNodeChanged();

		/**
		 * Returns true if this node is connected (or is the same as) the node given
		 * by other connectors or nodes (although not through CNItems)
		 * checkedNodes is a list of nodes that have already been checked for
		 * being the connected nodes, and so can simply return if they are in there.
		 * If it is null, it will assume that it is the first ndoe & will create a list
		 */
		bool isConnected( Node *node, NodeList *checkedNodes = nullptr ) override;
		/**
		 * Sets the node's visibility, as well as updating the visibility of the
		 * attached connectors as appropriate
	 	*/		
		void setVisible( bool yes ) override;
		/**
		 * Registers an input connector (i.e. this is the end node) as connected
		 * to this node.
	 	*/
		void addConnector( Connector * const connector );
		/**
		 * Creates a new connector, sets this as the end node to the connector
		 * and returns a pointer to the connector.
		 */
		Connector* createConnector( Node * node);

		// TODO oups, the following two methods do the same thing. Only one is needed.
		/**
		 * Returns a list of the attached connectors; implemented inline
	 	*/
		ConnectorList connectorList() const { return m_connectorList; }

		/**
		 * @return the list of all the connectors attached to the node
		 */
		ConnectorList getAllConnectors() const override { return m_connectorList; }
		
		/**
		 * Removes all the NULL connectors
	 	 */
		void removeNullConnectors() override;

		/**
		 * Returns the total number of connections to the node. This is the number
		 * of connectors and the parent
		 * item connector if it exists and is requested.
		 * @param includeParentItem Count the parent item as a connector if it exists
		 * @param includeHiddenConnectors hidden connectors are those as e.g. part of a subcircuit
	 	*/
		int numCon( bool includeParentItem, bool includeHiddenConnectors ) const override;
		/**
		 * Removes a specific connector
		 */
		void removeConnector( Connector *connector ) override;

		/**
		 * For an electric node: returns the first connector
		 * If the node isn't connected to anyithing, returns null ( 0 )
		 * @return pointer to the desired connector
		 */
		Connector* getAConnector() const override ;
		
	signals:
		void numPinsChanged( unsigned newNum );

	public slots:
		// -- from node.h --
		void checkForRemoval( Connector *connector );

	protected slots:
		void removeElement( Element * e );
		void removeSwitch( Switch * sw );

	protected:
		bool m_bShowVoltageBars;
		bool m_bShowVoltageColor;
		double m_prevV;
		double m_prevI;
		KtlQCanvasRectangle * m_pinPoint;
		PinVector m_pins;

		// -- functionality from node.h --
		/** If this node has precisely two connectors emerging from it, then this
		 * function will trace the two connectors until the point where they
		 * diverge; this point is returned.
		 * TODO: find a meaning for this function, for an electronic node...
		 */
		QPoint findConnectorDivergePoint( bool * found ) override;
		
		/** The attached connectors to this electronic node. No directionality here */
		ConnectorList m_connectorList;

		/** (please document this) registers some signals for the node and the new connector (?) */
		bool handleNewConnector( Connector * newConnector );
};

#endif

