/***************************************************************************
 *   Copyright (C) 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 SWITCH_H
#define SWITCH_H

#include <qguardedptr.h>
#include <qobject.h>

class CircuitDocument;
class Component;
class Pin;
class Resistance;
class QTimer;

/**
@author David Saxton
*/
class Switch : public QObject
{
	Q_OBJECT
	
	public:
		enum State
		{
			Open,
			Closed,
		};
		
		Switch( Component * parent, Pin * p1, Pin * p2, State state );
		~Switch();
		/**
		 * If bouncing has been set to true, then the state will not switch
		 * immediately to that given.
		 */
		void setState( State state );
		State state() const { return m_state; }
		/**
		 * Tell the switch whether to bounce or not, for the given duration,
		 * when the state is changed.
		 */
		void setBounce( bool bounce, int msec = 5 );
		/**
		 * Tell the switch to continue bouncing (updates the resistance value).
		 * Called from the simulator.
		 */
		void bounce();
		/**
		 * Attempts to calculate the current that is flowing through the switch.
		 * (If all the connectors at one of the ends know their currents, then
		 * this switch will give the current to the pins at either end).
		 * @return whether it was successful.
		 * @see CircuitDocument::calculateConnectorCurrents
		 */
		bool calculateCurrent();
		
	protected slots:
		/**
		 * Called from a QTimer timeout - our bouncing period has come to an
		 * end. This will then fully disconnect or connect the pins depending
		 * on the current state.
		 */
		void stopBouncing();

	protected:
		void startBouncing();
		
		bool m_bBounce;
		int m_bouncePeriod_ms;
		unsigned long long m_bounceStart; // Simulator time that bouncing started
		Resistance * m_pBounceResistance;
		State m_state;
		Component * m_pComponent;
		QGuardedPtr<Pin> m_pP1;
		QGuardedPtr<Pin> m_pP2;
		QTimer * m_pStopBouncingTimer;
};

#endif
