/*
    knetd, KDE Network Daemon

    Copyright (c) 2005 by Engin AYDOGAN		<engin @ bzzzt.biz>

    *************************************************************************
    *                                                                       *
    * 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 ABSTRACT_DEVICE_WRAP_H_
#define ABSTRACT_DEVICE_WRAP_H_

#include <qobject.h>

class AccessPoint;

/**
 * This class defines the interface of a network device.
 * Any network interface device implementation should derive from this
 * class and provide the interface. No matter if you're reading from /proc/net
 * or `ifconfig` like tools this is the base class you should use.
 */
class AbstractDevice : public QObject
{
Q_OBJECT
public:
	/** Speed of the link */
	enum Speed{
		    SpeedUnknown,	/*! Unknown speed */
		    Speed10,		/*! 10 Mbits */
		    Speed100,		/*! 100 Mbits */
		    Speed1000		/*! 1000 Mbits */
		  };

	/** Duplexity of the link*/
	enum Duplex {
		      DuplexUnknown,	/*! Unknown duplexity */
		      Full,		/*! Full duplex link */
		      Half		/*! Half duplex */
		    };

	/**
	 * Creates device by name. i.e. eth0, eth1, wlan0 etc.
	 * \param name name of the network inteface
	 */
	AbstractDevice( const QString& name )
	: QObject( 0, name ), m_name( name ) {}

	/**
	 * \return name of the network interface. i.e. eth0
	 */
	const QString&
	name() const { return m_name; }

	/**
	 * \return true if such a network interface exists
	 * \sa isEthernet(), isLinkUp(), isUp()
	 */
	virtual bool
	isAvailable() const = 0;

	/**
	 * Compares two devices according to their name.
	 * \param dev another device to compare
	 * \return true if the devices are the same
	 */
	virtual bool
	operator==( const AbstractDevice& dev )
	{
		return name() == dev.name();
	}

	/**
	 * @return true if the device is a wireless interface
	 */
	virtual bool
	isWireless() const = 0;

	/**
	 * @return true if the device is an Ethernet interface
	 *	   i.e. not loop back device
	 */
	virtual bool
	isEthernet() const = 0;

	/**
	 * @return hardware address of the device i.e. 00:0D:56:3B:F7:50
	 */
	virtual const QString&
	mac() const = 0;

	/**
	 * \return netmask of the device. i.e. 255.255.255.0
	 */
	virtual const QString&
	netmask() const = 0;

	/**
	 * \return default gateway of the device i.e. 192.168.0.1
	 */
	virtual const QString&
	gateway() const = 0;

	/**
	 * \return true if the network cable is plugged or associated with
	 *	   with a wireless access point.
	 */
	virtual bool
	isLinkUp() const = 0;

	/**
	 * \return the speed of the link
	 */
	virtual Speed
	speed() const = 0;

	/**
	 * \return the duplixity of the link
	 */
	virtual Duplex
	duplex() const = 0;

	/**
	 * \return IPv4 address of the device
	 */
	virtual const QString&
	ip4() const = 0;

	/**
	 * \return IPv6 address of the device
	 */
	virtual const QString&
	ip6() const = 0;

	/**
	 * \return true if the interface is up
	 */
	virtual bool
	isUp() const = 0;

public slots:
	/**
	 * Forces a link status check
	 */
	virtual void
	checkLink() = 0;

	/**
	 * Forces a signal check
	 */
	virtual void
	checkSignal() = 0;

	/**
	 * Forces a access point search
	 */
	virtual void
	checkAccessPoints() = 0;

	/**
	 * Forces a check on if the device is UP or DOWN
	 */
	virtual void
	checkUpDown() = 0;
signals:
	/**
	 * Emitted when an IP (v4 or v6) change detected on the device
	 */
	void ipChanged( AbstractDevice* );

	/**
	 * Emitted when the interface status changed to Up
	 */
	void interfaceUp( AbstractDevice* );

	/**
	 * Emitted when the interface status changed to Down
	 */
	void interfaceDown( AbstractDevice* );

	/**
	 * Emitted when the network cable plugged or associated 
	 * with an access point
	 */
	void linkUp( AbstractDevice* );

	/**
	 * Emitted when the network cable is unplugged or association
	 * with the access point is lost
	 */
	void linkDown( AbstractDevice* );

	/**
	 * Emitted when the signal strength to the access point changed
	 */
	void signalChanged( AbstractDevice*, int );

	/**
	 * Emitted when a new access point is found
	 */
	void apFound( AbstractDevice*, const AccessPoint* );

	/**
	 * Emitted when a known access point is lost
	 */
	void apLost( AbstractDevice*, const AccessPoint* );
private:
	QString m_name;
};

#endif
