/***************************************************************************
    smb4kscanner.h  -  The network scan core class of Smb4K.
                             -------------------
    begin                : Sam Mai 31 2003
    copyright            : (C) 2003-2008 by Alexander Reinholdt
    email                : dustpuppy@users.berlios.de
 ***************************************************************************/

/***************************************************************************
 *   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.                                   *
 *                                                                         *
 *   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     *
 *   General Public License for more details.                              *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,   *
 *   MA  02111-1307 USA                                                    *
 ***************************************************************************/

#ifndef SMB4KSCANNER_H
#define SMB4KSCANNER_H

#ifndef HAVE_CONFIG_H
#include <config.h>
#endif

// Qt includes
#include <QObject>
#include <QQueue>
#include <QList>

// KDE includes
#include <kprocess.h>
#include <kdemacros.h>

// application specific includes
#include "smb4kdefs.h"

// forward declarations
class Smb4KScannerPrivate;
class Smb4KScannerQueueContainer;
class Smb4KWorkgroup;
class Smb4KHost;
class Smb4KShare;


/**
 * This is the core class, that communicates with the network. All look-up
 * stuff is done here.
 *
 * @author Alexander Reinholdt <dustpuppy@mail.berlios.de>
 */

class KDE_EXPORT Smb4KScanner : public QObject
{
  Q_OBJECT

  public:
    /**
     * The constructor.
     *
     * @param parent          The parent of this class.
     */
    Smb4KScanner( QObject *parent = 0 );

    /**
     * The destructor.
     */
    ~Smb4KScanner();

    /**
     * Defines the protocol that is to be used with the 'net' command.
     */
    enum Protocol{ Auto,
                   RPC,
                   RAP,
                   ADS };

    /**
     * Initiates a network scan.
     *
     * Please not that after having invoked this function, the list of workgroups
     * as well as the list of known hosts will be cleared and refilled. Thus, all
     * known hosts except the current workgroup master browsers will have been
     * vanished.
     */
    void rescan();

    /**
     * Aborts the network scan.
     */
    void abort();

    /**
     * Reads the options.
     */
    void readOptions();

    /**
     * Query the host represented by @p host for its list of shared resources.
     *
     * @param host            The Smb4KHostItem representing the host.
     */
    void getShares( Smb4KHost *host );

    /**
     * Query a master browser for the workgroup/domain members.
     *
     * @param workgroup       The Smb4KWorkgroup that contains the master
     *                        browser that should be queried.
     */
    void getWorkgroupMembers( Smb4KWorkgroup *workgroup );

    /**
     * Get more info about a host (i.e. server and OS string, etc.). If the
     * information was already gathered, this function immediately emits the
     * info() signal with the requested information and exits. If no information
     * was requested before, a query is started.
     *
     * @param host            The Smb4KHost item representing the host
     */
    void getInfo( Smb4KHost *host );

    /**
     * This function reports if the scanner is running or not.
     *
     * @returns             TRUE if the scanner is running and FALSE otherwise.
     */
    bool isRunning() { return m_working; }

    /**
     * This function inserts a @p host into the list of known servers. If it belongs to
     * a workgroup that was not known until now, a new Smb4KWorkgroup item is also
     * created and added to the list of known workgroups. @p host is then marked as
     * pseudo master browser. On success, this function emits the hostAdded() and
     * hostListChanged() signals. If the host is already known, nothing is done.
     *
     * @param host          The host that should be inserted
     */
    void insertHost( Smb4KHost *host );

    /**
     * This function initializes the network the network browser. It starts the internal
     * timer that is needed to process the incoming requests and also starts the initial
     * network scan. You need to call this function before any other.
     */
    void init();

  signals:
    /**
     * This signal emits the run state.
     *
     * @param state         The so-called run state. There are several defined
     *                      in the smb4kdefs.h header file.
     */
    void state( int state );

    /**
     * This signal is emitted, when the workgroup list has been updated.
     *
     * @param list          The list of workgroups in the network neighborhood.
     */
    void workgroups( const QList<Smb4KWorkgroup *> &list );

    /**
     * Emits the list of workgroup members.
     *
     * @param workgroup     The workgroup in which the members are located
     *
     * @param list          The list of workgroup members.
     */
    void members( const QString &workgroup, const QList<Smb4KHost *> &list );

    /**
     * Emits the list of shares.
     *
     * @param host          The host that carries the shares
     *
     * @param list          The list of shares
     */
    void shares( const QString &host, const QList<Smb4KShare *> &list );

    /**
     * This signal is emitted if addtional information for the host represented
     * by @p host was requested and is available.
     *
     * @param host          The Smb4KHost item that carries the requested information.
     */
    void info( Smb4KHost *host );

    /**
     * This signal emits the host item for which an IP address has
     * been found.
     *
     * @deprecated Use Smb4KIPAddressScanner::ipAddress() instead.
     *
     * @param host          The host item with the new IP address
     */
    void ipAddress( Smb4KHost *host ) KDE_DEPRECATED;

    /**
     * This signal is emitted when the list of hosts is changed.
     */
    void hostListChanged();

    /**
     * This signal is emitted if a request could not be processed
     * successfully.
     */
    void failed();

    /**
     * This signal is emitted when a host has been added to the list of known
     * hosts via the insertHost() function.
     *
     * @param host          The Smb4KHost that represents the host that was added.
     */
    void hostInserted( Smb4KHost *host );

  protected:
    /**
     * Starts the process.
     *
     * @param state         The state
     */
    void startProcess( int state );

    /**
     * Is called, when the process ended. It either calls one of the
     * process*() functions if the process exited normally or throws
     * an error if a problem occurred.
     *
     * @param exitCode           The exit code of the process
     *
     * @param exitStatus         The exit status of the process (@see QProcess::ExitStatus)
     */
    void endProcess( int exitCode,
                     QProcess::ExitStatus exitStatus );

    /**
     * Processes the output of the network group scan.
     */
    void processWorkgroups();

    /**
     * Processes the list of workgroup members retrieved by
     * scanning the workgroup master browser.
     */
    void processWorkgroupMembers();

    /**
     * Processes the output of the host scan.
     */
    void processShares();

    /**
     * Processes the output of the scan for the OS and Server string.
     *
     * If the process finished successfully (i.e. @p status has the
     * value QProcess::NormalExit), the information will be
     * passed to the appropriate Smb4KHost object if it is available.
     * Otherwise the failed() signal will be emitted. The host won't
     * be checked anymore afterwards.
     *
     * If the process crashed, the host will be checked again next
     * time the additional information is requested.
     *
     * @param status              The exit status of the process.
     */
    void processInfo( QProcess::ExitStatus status );

    /**
     * Process the data from the IP range scan.
     */
    void processIPScan();

    /**
     * Reimplemented from QObject to process the incoming
     * data.
     *
     * @param event               The QTimerEvent event
     */
    void timerEvent( QTimerEvent *event );

  protected slots:
    /**
     * This slot is called, when the process exited.
     *
     * @param exitCode           The exit code of the process
     *
     * @param exitStatus         The exit status of the process (@see QProcess::ExitStatus)
     */
    void slotProcessFinished( int exitCode,
                              QProcess::ExitStatus exitStatus );

    /**
     * This slot is invoked when an error occurred with the process.
     *
     * @param errorCode       The error code returned by the process
     */
    void slotProcessError( QProcess::ProcessError errorCode );

  private:
    /**
     * Lookup all domains available on your network neighborhood. This is
     * done by nmblookup.
     */
    void lookupDomains();

    /**
     * Query a master browser for the domains available on your system. This
     * is either the current domain master browser or the one that was chosen
     * by the user.
     */
    void queryMasterBrowser();

    /**
     * Lookup all servers (and thus master browsers and domains) that have been
     * registered in the broadcast areas that were provided by the user.
     */
    void scanBroadcastAreas();

    /**
     * Scans the group master for the group members.
     */
    void scanForWorkgroupMembers( const Smb4KWorkgroup &workgroup );

    /**
     * Scans the chosen host for its shares. This is the private part
     * of @see Smb4KScanner::getShares().
     */
    void scanForShares( const Smb4KHost &host );

    /**
     * Scans a given host for its OS and Server string.
     */
    void scanForInfo( const Smb4KHost &host );

    /**
     * This function takes an Smb4KWorkgroup item and appends it to the list,
     * if the represented workgroup isn't already in it.
     *
     * @param item            The Smb4KWorkgroup object that is to be appended.
     */
    void appendWorkgroup( Smb4KWorkgroup *item );

    /**
     * Internal enumeration.
     */
    enum TODO{ Workgroups,
               QueryHost,
               IPScan,
               Hosts,
               Shares,
               Info,
               Init,
               Idle };

    /**
     * The main KProcess object.
     */
    KProcess *m_proc;

    /**
     * This queue stores the incoming requests until they are processed.
     */
    QQueue<Smb4KScannerQueueContainer> m_queue;

    /**
     * Is set to true, if the scanner is running.
     */
    bool m_working;

    /**
     * The internal state of the main process. Do not mix this up with
     * the state that's emitted to notify the application about changes.
     */
    int m_state;

    /**
     * If the process was aborted, this property is TRUE and FALSE
     * otherwise
     */
    bool m_aborted;

    /**
     * The process error code
     */
    QProcess::ProcessError m_process_error;

    /**
     * This is the pointer to the private helper class.
     */
    Smb4KScannerPrivate *m_priv;
};
#endif
